0

I'm fairly new to pandas, and was getting the infamous SettingWithCopyWarning in a large piece of code. I boiled it down to the following:

import pandas as pd
df = pd.DataFrame([[0,3],[3,3],[3,1],[1,1]], columns=list('AB'))
df
df = df.loc[(df.A>1) & (df.B>1)]
df['B'] = 10

When I run this I get the warning:

main:1: SettingWithCopyWarning: 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

The strange thing is that if I leave off the "df" line it runs without a warning. Is this intended behavior?

In general, if I want to filter a DataFrame by the values across various columns, do I need to do a copy() to avoid the SettingWithCopyWarning?

thanks very much

errg
  • 31
  • 4
  • My question is why am I getting a warning at all. Unless you always have to use the .copy() when you're getting a subset of a DataFrame – errg Nov 14 '18 at 05:19
  • @ errg see my answer and the page i referred that will help i beleive. – Karn Kumar Nov 14 '18 at 05:20
  • another [link on this](https://stackoverflow.com/questions/20625582/how-to-deal-with-settingwithcopywarning-in-pandas) with the great details ... – Karn Kumar Nov 14 '18 at 05:26
  • hese two chained operations execute independently, one after another. The first is an access method (get operation), that will return a DataFrame containing all rows at column A & B atr >1 . The second is an assignment operation (set operation), that is called on this new DataFrame with the changed data. We are not operating on the original DataFrame at all rather ob changed dataset – Karn Kumar Nov 14 '18 at 05:36
  • 1
    Thanks for your help. I guess the point is that when I've done: df = df.loc[(df.A>1) & (df.B>1)], even though I've thrown away the original DataFrame, df is still considered to be a slice into it, and I need to explicitly do a copy if I want to modify it. – errg Nov 14 '18 at 18:27
  • Okay, hope you will get your answer. – Karn Kumar Nov 14 '18 at 18:32

1 Answers1

0

Assuming your DataFrame as below from your question, this will avoid SettingWithCopyWarning

There is github Discussion and solution suggested by one of the Pandas developer Jeff :)

df
   A  B
1  3  3

Best to use this way.

df['B'] = df['B'].replace(3, 10)
df
   A   B
1  3  10
Ken Williams
  • 22,756
  • 10
  • 85
  • 147
Karn Kumar
  • 8,518
  • 3
  • 27
  • 53