关于SettingwithCopyWarning 的恍然大悟

SettingwithCopyWarning警告

用pandas写代码时,遇到了这个问题,虽说是个警告,不影响,但强迫症百度了许久找不到正解,

刚才发现了一个博客,写的很透彻(英文原版,中文翻译版)。

主要看到博客最后引用了一句话,看了我觉得很有必要解决这个BUG,这句话是这么说的:

there are no cases that I am aware of that you should actually ignore this warning. ... If you do certain types of indexing it will never work, others it will work. You are really playing with fire.


博客精华总结如下:

SettingwithCopyWarning 是啥

你操作的是数据的copy,不是原始数据

SettingwithCopyWarning 产生的原因

1. 二次链式索引

data[data.bidder == 'parakeet2004']['bidderrate'] = 100,这就是二次索引。这两次方括号索引的代码执行时分开的。

第一个方括号用于access(获取),[data.bidder == 'parakeet2004']返回一个data的一个子集的copy。

第二个方括号['bidderrate']用于assignment(赋值),它在刚才得到的copy上操作,不是在原始数据上操作

2. 比较久远的二次链式索引。。。

在实际写代码的时候,代码量往往比较大。比如

winners = data.loc[data.bid == data.price]

# 此处省略100行代码

winners.loc[304, 'bidder'] = 'therealname'

这时SettingwithCopyWarning又出现了,因为winner本身已经索引过一次了,再次使用winner进行索引的时候,就是在使用链式索引了

SettingwithCopyWarning的解法

1. 直接的二次索引

当我们在情景1(上面的原因1)时,我们的意图是想直接修改原始数据的,这时直接两个方括号修改的copy,我们应该这么写:

# 用loc直接定位

data.loc[data.bidder == 'parakeet2004', 'bidderrate'] = 100

2. 操作原始的数据的copy

当我们在情景2(上面的原因2)时,我们可能就是想在副本上修改,而不修改原始数据,这时我们要显示的告诉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

SettingwithCopyWarning 的意义:

1. 如果想要改变原始数据,用loc获iloc直接赋值

2. 如果想修改副本,就直接强制pandas这么去做

这样会使节约时间,让代码显得更无懈可击

there are no cases that I am aware of that you should actually ignore this warning. ... If you do certain types of indexing it will never work, others it will work. You are really playing with fire.

你可能感兴趣的:(关于SettingwithCopyWarning 的恍然大悟)