21

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

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

得到 SettingWithCopyWarning 后,我尝试了 using.loc:

complete.loc[:, 'AgeGt15'] = complete['Age'] > 15
complete.loc[:, 'WithFamily'] = complete['SibSp'] + complete['Parch'] > 0

但是,我仍然收到相同的警告。是什么赋予了?

4

3 回答 3

25

注意:从 pandas 0.24 版开始,is_copy已弃用,将在未来版本中删除。虽然私有属性_is_copy存在,但下划线表示该属性不是公共 API 的一部分,因此不应依赖。因此,展望未来,保持沉默的唯一正确方法似乎是在SettingWithCopyWarning全球范围内这样做:

pd.options.mode.chained_assignment = None

complete = train.dropna()被执行时,dropna可能会返回一个副本,因此出于谨慎考虑,Pandas 设置complete.is_copy为一个 Truthy 值:

In [220]: complete.is_copy
Out[220]: <weakref at 0x7f7f0b295b38; to 'DataFrame' at 0x7f7eee6fe668>

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

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

complete.is_copy = False       # deprecated as of version 0.24

这比制作实际副本更快,并且将SettingWithCopyWarning其扼杀在萌芽状态(在被调用的地方_check_setitem_copy):

def _check_setitem_copy(self, stacklevel=4, t='setting', force=False):
    if force or self.is_copy:
        ...

如果您真的有信心知道自己在做什么,则可以使用以下命令关闭SettingWithCopyWarning全局

pd.options.mode.chained_assignment = None # None|'warn'|'raise'

使警告静音的另一种方法是制作一个新副本:

complete = complete.copy()

但是,如果 DataFrame 很大,您可能不想这样做,因为复制可能会占用大量时间和内存,并且如果您知道已经是副本,则完全没有意义(除了为了消除警告)。complete

于 2016-08-07T01:08:52.687 回答
3

我通过创建数据框的副本来解决它:

complete = train.copy()
于 2018-10-02T05:35:12.620 回答
0

.loc如果不是np.nan原始数据框中的 s ,我认为您的解决方案会起作用。您可以complete = train.dropna().reset_index()或者Pandas .assign()将避免SettingWithCopyWarning并且是创建新列的推荐方法,返回一个新的数据框对象。你的例子:

complete = complete.assign(**{'AgeGt15': np.where(complete['Age'] > 15, True, False)})
于 2019-11-08T12:29:14.863 回答