解决:SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame

在使用pandas时遇到了一个问题:SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame
翻译:(你)试图改变DataFrame(类似于一个pandas向量)中的一个副本中的值
解决方法就是使用loc
执行代码如下:

import pandas as pd
import numpy as np

aa=np.array([1,2,3,4])
bb=pd.DataFrame(aa.T,columns=['first'])
print(bb,'\n***********')
bb['two']=0
print(bb,'\n***********')
bb['first'][0]=3
print(bb)

输出如下:

first
0 1
1 2
2 3
3 4


first two
0 1 0
1 2 0
2 3 0
3 4 0


Warning (from warnings module):
File “D:/pProject/mlRegression/meaningless.py”, line 9
bb[‘first’][0]=3
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
first two
0 3 0
1 2 0
2 3 0
3 4 0

我们看Warning 提出的帮助文档:
在这里插入图片描述

也就是说,这就类似于C++中传入函数的参数只是形参,在这里是__getitem__()函数,如果你在函数中尝试改变形参是毫无意义的,python 就会发出警告。

解决方案
方案就是用它提示的loc函数

import pandas as pd
import numpy as np

aa=np.array([1,2,3,4])
bb=pd.DataFrame(aa.T,columns=['first'])
print(bb,'\n***********')
bb['two']=0
print(bb,'\n***********')
#bb['first'][0]=3
bb.loc['first',0]=3#改用loc
print(bb)

loc函数保证返回的是bb本身(类似于C++的引用,而不是bb的一个副本)

再举类似一个例子

import pandas as pd
import numpy as np

aa=np.array([1,2,3,4])
bb=pd.DataFrame(aa.T,columns=['first'])
bb['two']=0

cc=bb.iloc[:,0]
cc[3]=13
print(bb)
print(cc)

输出结果:

Warning (from warnings module):
  File "D:\pProject\mlRegression\meaningless.py", line 9
    cc[3]=13
SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
   first  two
0      1    0
1      2    0
2      3    0
3     13    0
0     1
1     2
2     3
3    13
Name: first, dtype: int32

可以看到,警告的事情发生了!
bb的值连带着cc的值发生了改变!说明cc是bb的一个引用,cc值改变会引起bb 改变
正确做法:用深copy(而不是浅copy)

import pandas as pd
import numpy as np

aa=np.array([1,2,3,4])
bb=pd.DataFrame(aa.T,columns=['first'])
bb['two']=0

cc=bb.iloc[:,0]
cc=cc.copy()#加上这么一句
cc[3]=13
print(bb)
print(cc)
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐