先看看下面的代码

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 的原理和解决方案