即使在使用.loc之后,Pandas仍然会获得SettingWithCopyWarning

Hue*_*uey 17 python pandas chained-assignment

起初,我尝试编写一些看起来像这样的代码:

import numpy as np
import pandas as pd
np.random.seed(2016)
train = pd.DataFrame(np.random.choice([np.nan, 1, 2], size=(10, 3)), 
                     columns=['Age', 'SibSp', 'Parch'])

complete = train.dropna()    
complete['AgeGt15'] = complete['Age'] > 15
Run Code Online (Sandbox Code Playgroud)

获得SettingWithCopyWarning后,我尝试使用.loc:

complete.loc[:, 'AgeGt15'] = complete['Age'] > 15
complete.loc[:, 'WithFamily'] = complete['SibSp'] + complete['Parch'] > 0
Run Code Online (Sandbox Code Playgroud)

但是,我仍然得到同样的警告.是什么赋予了?

unu*_*tbu 20

注意:从pandas版本0.24开始,is_copy不推荐使用,将在以后的版本中删除.虽然private属性_is_copy存在,但下划线表示此属性不是公共API的一部分,因此不应依赖它.因此,向前看,似乎唯一正确的沉默SettingWithCopyWarning方式是在全球范围内这样做:

pd.options.mode.chained_assignment = None
Run Code Online (Sandbox Code Playgroud)

complete = train.dropna()被执行时,dropna可能会返回一个副本,因此出于谨慎的,大熊猫将complete.is_copy到Truthy值:

In [220]: complete.is_copy
Out[220]: <weakref at 0x7f7f0b295b38; to 'DataFrame' at 0x7f7eee6fe668>
Run Code Online (Sandbox Code Playgroud)

这允许Pandas稍后警告你,complete['AgeGt15'] = complete['Age'] > 15执行时你可能正在修改一个不会影响的副本train.对于初学者来说,这可能是一个有用的警告.在您的情况下,您似乎无意通过修改train间接修改complete.因此,在您的情况下,警告只是一种毫无意义的烦恼.

您可以通过设置使警告静音

complete.is_copy = False       # deprecated as of version 0.24
Run Code Online (Sandbox Code Playgroud)

这是不是让实际的复制更快,而且咬SettingWithCopyWarning在萌芽状态(点这里_check_setitem_copy被称为):

def _check_setitem_copy(self, stacklevel=4, t='setting', force=False):
    if force or self.is_copy:
        ...
Run Code Online (Sandbox Code Playgroud)

如果你真的很自信你知道自己在做什么,那么就可以SettingWithCopyWarning全局关闭

pd.options.mode.chained_assignment = None # None|'warn'|'raise'
Run Code Online (Sandbox Code Playgroud)

  • @ayhan:如果`complete = complete.assign(AgeGt15 =(complete ['Age']> 15))`,也没有警告.Pandas用来推断`SettingWithCopyWarning`的机制不是万无一失的.它捕获了最常见的情况,但不是全部. (2认同)