简体   繁体   中英

Setting a value to a pandas DataFrame: Warning A value is trying to be set on a copy of a slice from a DataFrame

Why is this? I'm going to make 4 dataframes in pandas:

>>> df = pd.DataFrame({"A": ["One","Two","Three"], "B": ["Two","Three","Four"], "C": ["Three","Four","Five"], "D": ["Four","Five","Six"]})
>>> df
       A      B      C     D
0    One    Two  Three  Four
1    Two  Three   Four  Five
2  Three   Four   Five   Six
>>> df["C"][1] = "One Hundred"

Everything worked well; now let's do two columns first then we add two columns, one with "" and the other one with NaN

>>> df = pd.DataFrame({"A": [1,2,3], "B": [2,3,4]})
>>> df
   A  B
0  1  2
1  2  3
2  3  4
>>> df["C"] = ""
>>> df["D"] = pd.np.nan
>>> df
   A  B C   D
0  1  2   NaN
1  2  3   NaN
2  3  4   NaN
>>> df["C"][1] = "hello"

Warning (from warnings module):
  File "__main__", line 1
SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

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

A Warning shows up! Ok: (this is the question: what is that warning for?) But let's continue:

now I do this:

>>> df = pd.DataFrame({"A": [1,2,3], "B": [2,3,4], "C": [3,4,5], "D": [4,5,6]})
>>> df
   A  B  C  D
0  1  2  3  4
1  2  3  4  5
2  3  4  5  6
>>> df["C"][1] = 100

and no Warning appears. ok.

Now let's trigger the warning again:

>>> df = pd.DataFrame({"A": [1,2,3], "B": [2,3,4]})
>>> df["C"] = ""
>>> df["D"] = pd.np.nan
>>> df
   A  B C   D
0  1  2   NaN
1  2  3   NaN
2  3  4   NaN
>>> df["C"][1] = "hello"
>>> 

NO WARNING THIS TIME!?

I'm using IDLE 3.5.2 , Python version: 3.5.2...

Is this a bug? I can't tell because I'm studying.

Should I write a new separate DataFrame with all the column and then just equal it to the df's column each time?

Should I make a python list?...

Is there a way to traverse and edit over the original dataframe without the warning?

Why isn't that warning popping up every time?

Thanks for your time.

You can using loc or iloc

df
Out[1445]: 
     A  A_1    B
0  1.0  1.0    A
1  NaN  NaN    A
2  3.0  3.0  NaN
3  4.0  4.0    B
df.iloc[1,1]='Yourvalue1'
df
Out[1447]: 
     A         A_1    B
0  1.0           1    A
1  NaN  Yourvalue1    A
2  3.0           3  NaN
3  4.0           4    B
df.loc[1,'A']
Out[1448]: nan
df.loc[1,'A']='Yourvalue2'
df
Out[1450]: 
            A         A_1    B
0           1           1    A
1  Yourvalue2  Yourvalue1    A
2           3           3  NaN
3           4           4    B

I think the right way to do it is to write a function and use it with the apply method.

df.apply(my_function, axis=1)

like shown here so that pandas can do its thing super fast.

The correct way is:

df["column_name"][0] = "hello"

If you use the dot column_name way you are selecting a slice apparently. if you use this (correct) method you are "touching the cell" so to speak.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM