官方 DOC
解决办法和说明:https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
按照说明,将想要使用的slice 后的 dataframe进行深拷贝,一般就解决了问题。但最好确定你的目的是什么,比如如果是 slice 后就是要改变具体某个值(在原内存上),那最好用.loc来做。或者目的就是生成新的 dataframe 然后做操作,那最好先 deepcopy 下。
以及如果有如下的操作,也大概率会报这个错误:
import pandas as pd
a = pd.DataFrame([list('abcd'),
list('efgh'),
list('ijkl'),
list('mnop')],
columns=pd.MultiIndex.from_product([['one', 'two'],
['first', 'second']]))
a_1 = a.loc["one"]
a_2 = a.loc["first"]
a_2 = list("kfif")
这样连续 loc 后的值想做改变,也会报错。此时最好直接:
a_2 = a.loc[("one", "first")]
# or
a_1 = a.loc["one"].copy()
就可以了。
中文熟肉解释
警告分析
这个警告常常在对一个dataframe进行切片的操作上。
SettingWithCopyWarning 告诉你,你的操作可能没有按预期运行,需要检查结果以确保没有出错。
如果代码确实按预期工作,那么我们会很容易忽略该警告,但是 SettingWithCopyWarning 不应该被忽略。
在进行下一步操作之前,我们需要花点时间了解这一警告显示的原因。
要了解 SettingWithCopyWarning,首先要知道,Pandas 中的某些操作会返回数据的视图(View),某些操作会返回数据的副本(Copy)。
返回视图,那么代表修改了原数据;
返回副本,那么代表产生了一个变量来保存数据;
底层原理是“链式索引”,即两个个索引操作连接在一起。
解决问题的方案
- 方案1(最正确的方案)
这种情况对应的解决方案很简单:使用 loc 将两次链式操作组合成一步操作,确保 Pandas 进行 Set 的是原始 DataFrame。
- 方案2
明确的将切片操作取copy() 对象。
- 方案3(最不建议,还是忘了吧。。。)
关闭pandas的警告
pd.set_option(‘mode.chained_assignment’, None)