先看看下面的代码
import numpy as np import pandas as pd np.random.seed(100) data = pd.DataFrame(np.random.randint(1, 10, size=(3, 4)), columns=list('abcd')) print(data) ### data2 = data['a'] data2['e'] = data['a'] - data['b'] print(type(data2)) # <class 'pandas.core.series.Series'> print(data2) # 0 9 # 1 8 # 2 6 # e 0 0 # 1 7 # 2 3 # dtype: int32 # Name: a, dtype: object 啥也不是,不是我们想要的 ### data3 = pd.DataFrame(data['a']) # 手动生成一个新的 df data3['e'] = data['a'] - data['b'] print(data3) # a e # 0 9 0 # 1 8 7 # 2 6 3 ### data4 = data[['a', 'b']] # data4['e'] = data['a'] - data['b'] # print(data4) # 报错如下 # 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
data 是一个 DataFrame,
data2 取了一列,得到一个 Series,竟然也能再添加一列,不过结果乱七八糟;
data3 也取了一列,手动生成 DataFrame,再添加一列,正常;
data4 取了两列,再添加一列,问题来了,报错
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
问题分析:
data4 选择了 df 的一部分,然后对其进行修改,此时 pandas 无法确定是在原来的 df 上做修改,还是复制一个新的 df 出来单独操作;
解决办法有3个:
1. copy 函数,明确复制出来一个
2. loc 选择器,也是明确复制一部分数据
3. 手动生成新的 df
## 解决方法1:copy方法 data4 = data[['a', 'b']].copy() data4['e'] = data['a'] - data['b'] print(data4) # a b e # 0 9 9 0 # 1 8 1 7 # 2 6 3 3 ## 解决方法2:loc选择器 data4 = data.loc[:, ['a', 'b']] data4['e'] = data['a'] - data['b'] print(data4) # a b e # 0 9 9 0 # 1 8 1 7 # 2 6 3 3 print(data) ## 解决方法3:手动生成DF data4 = pd.DataFrame(data[['a', 'b']]) data4['e'] = data['a'] - data['b'] print(data4)
更多理论见 参考资料2
参考资料:
http://www.python66.com/pandasshujufenxi/284.html
https://www.jianshu.com/p/72274ccb647a Pandas 中 SettingwithCopyWarning 的原理和解决方案