1

This seems like something simple. But I've tried several different things and read probably a dozen StackOverflow questions that seemed related.

I have market data for crypto currnecies (BitCoin and others). The Order Book is a list of all the 'asks' and 'bids' for a given currency. I am wanting to store the data in a Pandas DataFrame. (I'm not stuck on using DFs just thought it might provide easier plotting down the road.)

So the setup right now is a DataFrame where the Rate (price) is the Index and it is a float. The quantity of coins available at that price is in a column named Amt.

When I get an update to the Amount at a given Rate I want to simply replace that value. Of all the possible solutions I found this option to be the most intuitive to me:

df.Amt[df.Rate == rate] = new_amt

While I don't get any errors from this, when I check to see if the Amt changes I find that it has not. I assume this is one of those copy/slice issues vs working on the DataFrame itself.

Example:

df.head()
Out[77]: 
       Rate        Amt
0  0.018021   0.319033
1  0.018009  29.994000
2  0.017999  28.121000
3  0.018042   2.233781
4  0.018055  13.433394

df.Amt[df.Rate == 0.018021] = 20

df.head()
Out[79]: 
       Rate        Amt
0  0.018021   0.319033
1  0.018009  29.994000
2  0.017999  28.121000
3  0.018042   2.233781
4  0.018055  13.433394

What am I missing? I've worked with DFs in the past to change whole columns but not generally just 1 row.

6
  • Are you trying to change all the values to 20 if df.Rate == 0.018021 or just df.Rate Commented Jun 3, 2017 at 0:33
  • Your problem is float equality. What displays as "1.02" might really be "1.019" for example. You don't really want to do float equalities generally speaking. I don't know the solution in your case, but perhaps something more like x > 0.017 & x < 0.019 Commented Jun 3, 2017 at 0:55
  • also, there is a numpy function isclose() that might help you. Commented Jun 3, 2017 at 0:56
  • @everestial007: I get near real-time data pushed to my code from the market. The data includes an exact rate and an exact amount at that rate. For example, there could be several buyers willing to buy up to a total of 0.5 at a rate (price) of 1. Some buys 0.3 at a rate of 1 so the market now updates me by telling me there is a total of 0.2 at a rate of 1. As a result, I need to change the amount at rate 1 from 0.5 to 0.2. Commented Jun 3, 2017 at 4:03
  • @JohnE The thought had occurred to me that the rates, as an index, were likely getting truncated. The trailing 0s being dropped. I did not think that head would round them. With regards to isclose(), that sounds like something that finds a nearest neighbor or something. In this case I am only interested in an exact match. I'll go dig into the docs. Commented Jun 3, 2017 at 4:05

1 Answer 1

2

Correcting the error and incorporating @JohnE's comment

You were accessing the pd.Series object with df.Amt and slicing it with [df.Rate == 0.018021]. When what you want is to pass the boolean array to loc and assign that way.

df.loc[np.isclose(df.Rate, 0.018021), 'Amt'] = 20

       Rate        Amt
0  0.018021  20.000000
1  0.018009  29.994000
2  0.017999  28.121000
3  0.018042   2.233781
4  0.018055  13.433394
Sign up to request clarification or add additional context in comments.

1 Comment

This appears to be more robust that np.equal in this case. The rates I'm provided are strings and the conversion to float is adding an error down at like 1E-12. An addition to the value that is meaningless to the math but keeps a strict match from actually matching. The np.close used with an atol of 1E-10 seems to work in early testing. Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.