在用pandas时出现这个警告(SettingWithCopyWarning) 表示你的操作可能没有按预期运行,你应该检查结果以确保没有出错。
一般很容易忽略警告,这不是良好的实践,SettingWithCopyWarning
不应该被忽略。
原文:https://www.dataquest.io/blog/settingwithcopywarning/
翻译:https://www.jianshu.com/p/72274ccb647a
产生警告的原因:
1.当 Pandas 检测链式赋值(Chained assignment)时会生成警告。
生成警告是因为我们将两个索引操作链接在一起,我们直接使用了两次方括号。
data[data.bidder == 'parakeet2004']['bidderrate'] = 100
但如果我们使用其他访问方法,例如 .bidderrate
、.loc[]
、.iloc[]
、.ix[]
,也是如此,我们的链式操作是:
data[data.bidder == 'parakeet2004']
['bidderrate'] = 100
这两个链式操作一个接一个地独立执行。第一次是访问操作(get),返回一个 DataFrame
,其中包含所有 bidder
等于 'parakeet2004'
的行。第二个是赋值操作(set),是在这个新的 DataFrame
上运行的,我们压根没有在原始 DataFrame
上运行。
这个解决方案很简单:使用 loc
将链式操作组合到一个操作中,以便 Pandas 可以确保 set 的是原始 DataFrame
。Pandas 会始终确保下面这样的非链式 set 操作起作用。
# 设置新值
data.loc[data.bidder == 'parakeet2004', 'bidderrate'] = 100
# 检查结果
data[data.bidder == 'parakeet2004']['bidderrate']
2.隐蔽的链式操作(Hidden chaining)
链式索引可能跨越两行代码发生,也可能在一行代码内发生。因为 winners
是作为 get 操作的输出创建的(data.loc[data.bid == data.price]
),它可能是原始 DataFrame
的副本,也可能不是,但除非我们检查,否则我们不能了解到。当我们对 winners
进行索引时,我们实际上使用的是链式索引。
这意味着当我们尝试修改 winners
时,我们可能也修改了 data
。
在实际的代码中,这些行可能会跨越很大的距离,因此追踪问题可能会更困难,但情况是与示例类似的。
为了防止这种情况下的警告,解决方案是在创建新 DataFrame 时明确告知 Pandas 制作一个副本:
winners = data.loc[data.bid == data.price].copy()
winners.loc[304, 'bidder'] = 'therealname'
print(winners.loc[304, 'bidder'])
print(data.loc[304, 'bidder'])
therealname
nan