4

Probably a trivial problem, but I need to understand what's going on here (and how to fix it).

Suppose I have a dataframe with columns 'a' and 'b', as follows:

f = pandas.DataFrame({'a':[1,2,3,4,5], 'b':[10,20,30,40,50]})

Now for every element of 'a' that is 3 or less, I want to divide the corresponding elements of 'b' by 10.

f[f['a']<=3]['b'] = (f[f['a']<=3]['b'])/10

So that the values in column 'b' should now be [1,2,3,40,50].

But I find that column 'b' remains unchanged! What gives?

user2383521
  • 323
  • 1
  • 4
  • 10

2 Answers2

7

I think you are trying to assign values to a copy rather than a view (f[f['a']<=3]['b'] is a copy), see Returning a view versus a copy.

However, you can reorder this and it'll work be a view:

In [11]: f['b'][f['a']<=3] = (f[f['a']<=3]['b'])/10

In [12]: f
Out[12]:
   a   b
0  1   1
1  2   2
2  3   3
3  4  40
4  5  50
Andy Hayden
  • 359,921
  • 101
  • 625
  • 535
  • 1
    To elaborate on Andy's answer, read http://pandas.pydata.org/pandas-docs/dev/indexing.html#indexing-view-versus-copy to understand what is happening. – Dan Allan May 14 '13 at 21:48
  • @DanAllan was just filling it in with that same link :) – Andy Hayden May 14 '13 at 21:50
  • @AndyHayden, would love to have a couple of more examples in 'Returning a view vs copy' section, as seem to have lots of questions (and confusion) in that regards... – Jeff May 14 '13 at 21:53
  • @Jeff agreed, I will try and put something together. *It is confusing, so it'll be a good thing to write down...* – Andy Hayden May 14 '13 at 22:03
0

Like answers just mentioned, its is a copy and view's issue.

And if I want to do this, I may choose this:

f['b'] = np.where(f['a'] <= 3, f['b']/10, f['b'])
#f

Out[26]:
a   b
0   1   1
1   2   2
2   3   3
3   4   40
4   5   50
staticor
  • 620
  • 9
  • 19