23

I get SettingWithCopyWarning errors in cases where I would not expect them:

N.In <38>: # Column B does not exist yet
N.In <39>: df['B'] = df['A']/25
N.In <40>: df['B'] = df['A']/50

/Users/josh/anaconda/envs/py27/lib/python2.7/site-packages/pandas/core/indexing.py:389: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
  self.obj[item] = s

and

N.In <41>: df.loc[:,'B'] = df['A']/50

/Users/josh/anaconda/envs/py27/lib/python2.7/site-packages/pandas/core/indexing.py:389: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
  self.obj[item] = s

Why does it happen in case 1 and 2?

Amelio Vazquez-Reina
  • 91,494
  • 132
  • 359
  • 564

2 Answers2

19

In case 1, df['A'] creates a copy of df. As explained by the Pandas documentation, this can lead to unexpected results when chaining, thus a warning is raised. Case 2 looks correct, but false positives are possible:

Warning: The chained assignment warnings / exceptions are aiming to inform the user of a possibly invalid assignment. There may be false positives; situations where a chained assignment is inadvertantly reported.

To turn off SettingWithCopyWarning for a single dataframe, use

df.is_copy = False

To turn off chained assignment warnings altogether, use

options.mode.chained_assignment = None
kxsong
  • 440
  • 4
  • 13
7

Another solution that should suppress the warning:

df = df.copy()
df['B'] = df['A']/25
df['B'] = df['A']/50
Charlie Haley
  • 4,152
  • 4
  • 22
  • 36
  • 3
    This does indeed work. Not fully understand if this is now faster or more memory consuming. I don't know the impact of the copy() command. Since in fact the copy is reassign again to df.. It looks like nothing is changed at the end. – Melroy van den Berg Jan 20 '17 at 12:24