24

Python 3.4 and Pandas 0.15.0

df is a dataframe and col1 is a column. With the code below, I'm checking for the presence of the value 10 and replacing such values with 1000.

df.col1[df.col1 == 10] = 1000

Here's another example. This time, I'm changing values in col2 based on index.

df.col2[df.index == 151] = 500

Both these produce the warning below:

-c:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

Finally,

cols = ['col1', 'col2', 'col3']
df[cols] = df[cols].applymap(some_function)

This produces a similar warning, with an added suggestion:

Try using .loc[row_indexer,col_indexer] = value instead

I'm not sure I understand the discussion pointed to in the warnings. What would be a better way to write these three lines of code?

Note that the operations worked.

Brad Solomon
  • 38,521
  • 31
  • 149
  • 235
ba_ul
  • 2,049
  • 5
  • 22
  • 35

2 Answers2

39

The issue here is that: df.col1[df.col1 == 10] returns a copy.

So I would say:

row_index = df.col1 == 10
# then with the form .loc[row_indexer,col_indexer]
df.loc[row_index, 'col1'] = 100
Paul H
  • 65,268
  • 20
  • 159
  • 136
5

Agreed with Paul about 'loc' usage.

For your applymap case you should be able to do this:

cols = ['col1', 'col2', 'col3']
df.loc[:, cols] = df[cols].applymap(some_function)
koelemay
  • 53
  • 4
  • 5
    That gives the same warning. But this one doesn't: df.loc[:, cols] = df.loc[:, cols].applymap(some_function) – ba_ul Nov 05 '14 at 02:31
  • Interesting. I'm using pandas 0.15.0 but Python 2.7.5 so didn't test with your environment. My suggestion does not throw the warning for me. Good to know that your latter attempt worked – koelemay Nov 05 '14 at 15:15
  • I'm getting the copy warning even though I'm using .loc: col_pct = ['Cash', 'Funds'] ui_df.loc[:, col_pct] = ui_df.loc[:, col_pct].applymap('{0:.2f}%'.format) – Tom Dec 24 '18 at 16:17