Python: SettingWithCopyWarning when trying to set value to True based on condition

Viewed 48

Data:

Date          Stock    Peak    Trough    Price
2002-01-01    33.78    False   False     25
2002-01-02    34.19    False   False     35
2002-01-03    35.44    False   False     33
2002-01-04    36.75    False   False     38

I use this line of code to set 'Peak' to true in each row whenever the price of a stock is higher or equal to the max value in the row starting from column 4:

df['Peak'] = np.where(df.iloc[:,4:].max(axis=1) >= df[stock], 'False', 'True')

However, I'm trying to make it so that the first X and last Y rows are not affected. Let's say X and Y are both 10 in this example. I modified it like this:

df.iloc[10:-10]['Peak'] = np.where(df.iloc[10:-10,4:].max(axis=1) >= df.iloc[10:-10][stock], 'False', 'True')

This gives me an error SettingWithCopyWarning and also doesn't work anymore. Does anyone have an idea how to get the desired result so that the first X and last Y rows are always False?

1 Answers

I believe you need a get_loc to specify column index when assigning using df.iloc[] :

df.iloc[10:,df.columns.get_loc('year')] = (np.where(df.iloc[10:,4:].max(axis=1)
                           >= df.iloc[10:,df.columns.get_loc('stock')],'False', 'True'))

To try here is a test case:

np.random.seed(123)
df = pd.DataFrame(np.random.randint(0,100,(5,4)),columns=list('ABCD'))
print(df)

    A   B   C   D
0  66  92  98  17
1  83  57  86  97
2  96  47  73  32
3  46  96  25  83
4  78  36  96  80

Trying to set column D as np.nan from index 2 we get the same error:

df.iloc[2:]['D']=np.nan

A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy """Entry point for launching an IPython kernel.

Trying the same avoiding a chained assignment using get_loc (successful)

df.iloc[2:,df.columns.get_loc('D')] = np.nan
print(df)
    A   B   C     D
0  66  92  98  17.0
1  83  57  86  97.0
2  96  47  73   NaN
3  46  96  25   NaN
4  78  36  96   NaN
Related