0

I have a dataframe:

jb = pd.DataFrame([ ['No', 75, 2.0], ['Blofeld', 140, 1.9], ['Chiffre', 114, 1.7]  ],
                 index=['b1', 'b5', 'b21'], columns=['Name', 'Weight', 'Height'])

Then if I do chained assignment as below, it won't change the original value in jb. And it will also trigger SettingWithCopyWarning .

jb[jb.Weight==75]['Height'] = 9

But if I switch the order of chained assignment, it will then change the original value in jb, but still also trigger SettingWithCopyWarning .

jb['Height'][jb.Weight==75] = 9

So the second code is still producing a copy but why it ends up modifying the original jb?

wwj123
  • 365
  • 2
  • 12

1 Answers1

1

You should not try to do what you call chained assignments. Pandas documentation states that it is unspecified whether you get a view (and change the original value) or a copy (and do not). AFAIK, it depends on implementation details and on the internals on Pandas optimization code.

That being said the observed behavious is no surprise. In a Pandas DataFrame, data is stored in numpy arrays by columns. So when you access first by column (your second code), Pandas can easily give you access to the underlying numpy array as a Series. But when you access first by row (your first code) Pandas has to build a new Series, and only give you a copy of the original data.

Nevertheless, the only reliable way is to use loc:

jb.loc[jb.Weight == 75, 'Height'] = 9
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • Yeah I understand loc[row,col] is the best solution here. I am just surprised that the second code still have the "SettingWithCopyWarning" when it is still working on the original value. I guess it is [jb.Weight==75] that's triggering the warning. But then a similar code such as s[s>2]=0 (s is just a simple Series of int) does not have such warning. Maybe it is really just a matter of how pandas optimize things. – wwj123 Jan 20 '22 at 22:40
  • @wwj123: Pandas doc does warn that the exact behaviour depends on the Pandas optimizes... – Serge Ballesta Jan 20 '22 at 22:48