Why does assignment fail when using chained indexing?
The problem in the previous section is just a performance issue. What’s up with the SettingWithCopy
warning? We don’t usually throw warnings around when you do something that might cost a few extra milliseconds!
But it turns out that assigning to the product of chained indexing has inherently unpredictable results. To see this, think about how the Python interpreter executes this code:
dfmi.loc[:, ('one', 'second')] = value
# becomes
dfmi.loc.__setitem__((slice(None), ('one', 'second')), value)
But this code is handled differently:
dfmi['one']['second'] = value
# becomes
dfmi.__getitem__('one').__setitem__('second', value)
See that __getitem__
in there? Outside of simple cases, it’s very hard to predict whether it will return a view or a copy (it depends on the memory layout of the array, about which pandas makes no guarantees), and therefore whether the __setitem__
will modify dfmi
or a temporary object that gets thrown out immediately afterward. That’s what SettingWithCopy
is warning you about!
Note
You may be wondering whether we should be concerned about the loc
property in the first example. But dfmi.loc
is guaranteed to be dfmi itself with modified indexing behavior, so dfmi.loc.__getitem__
/ dfmi.loc.__setitem__
operate on dfmi
directly. Of course, dfmi.loc.__getitem__(idx)
may be a view or a copy of dfmi
.
Sometimes a SettingWithCopy warning will arise at times when there’s no obvious chained indexing going on. These are the bugs that SettingWithCopy is designed to catch! Pandas is probably trying to warn you that you’ve done this:
def do_something(df):
foo = df[['bar', 'baz']] # Is foo a view? A copy? Nobody knows!
# ... many lines here ...
# We don't know whether this will modify df or not!
foo['quux'] = value
return foo
Yikes!
You can safely disable this warning with the following assignment.
import pandas as pd
pd.options.mode.chained_assignment = None # default='warn'
Refrence:
https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy