为啥这段代码会引发 SettingWithCopyWarning? [复制]

Posted

技术标签:

【中文标题】为啥这段代码会引发 SettingWithCopyWarning? [复制]【英文标题】:Why does this code throw a SettingWithCopyWarning? [duplicate]为什么这段代码会引发 SettingWithCopyWarning? [复制] 【发布时间】:2018-04-05 22:25:54 【问题描述】:

所以我正在尝试创建一个新列来指示指定条件是否为真。我希望该列简单地说明“1”或“0”。

这是我的代码:

data_sub = data_orig.loc[~pd.isnull(data_orig['Last_Audit_Date']), :]
data_sub.reset_index(inplace=True)
data_sub['PackageLengthFlag'] = (abs(data_sub.loc['AUDIT_Primary_Length'] - data_sub.loc[:, 'PKG_SUB_Length']) > threshold)

我认为 True = 1 和 False = 0 默认情况下,如果我将其转换为整数,对吗? (以为我在某处读到过这样的说法……)

这是我不断收到的警告:

SettingWithCopyWarning:  A value is trying to be set on a copy of 
a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead

我读到了:

How to deal with SettingWithCopyWarning in Pandas?

Correct way to set value on a slice in pandas

Pandas SettingWithCopyWarning

但我不认为他们做我想要的。 有人有什么建议吗?我知道这个问题可能听起来很愚蠢,但仍然感谢任何帮助!

编辑 我在创建 data_sub 的地方添加了 2 行代码。希望对您有所帮助!

【问题讨论】:

此错误的来源不在这里,但可能在此之前的代码中。您可能尝试在不调用 .copy 的情况下提取数据帧的一些子片段,这会产生此错误。 您很可能会收到该警告,因为 data_sub 是切片的副本 没有样本 df 很难猜到,但这应该可以。 data_sub['PackageLengthFlag'] = (np.abs(data_sub['AUDIT_Primary_Length'] - data_sub['PKG_SUB_Length']) > 阈值).astype(int) 我在创建 data_sub 的地方添加了 2 行代码。希望有帮助! 【参考方案1】:

错误出现在上面的代码中,当您尝试提取一些数据帧子切片而不制作完整副本时,您拥有的引用实际上是对另一个更大数据帧的一部分的引用。

没有太多关于您要做什么的上下文,只需事先制作一份副本:

data_sub = data_sub.copy()
data_sub['PackageLengthFlag'] = (
    data_sub['AUDIT_Primary_Length']
        .sub(data_sub['PKG_SUB_Length'])
        .abs()
        .gt(threshold)
        .astype(int)

调用df.abs 对整个结果执行abs 函数。 abs 是一种无法处理 pd.Series 对象的普通 python 方法。

最后一次astype 调用将结果转换为整数值。


这是你正在做的一个例子:

df

  A_Key B_ID C_Key  D_NA
0   123   22   343    23
1   121   23  45.4    52

x = df.iloc[[0], :]
x

  A_Key B_ID C_Key  D_NA
0   123   22   343    23

x.iloc[:, 0] += 2
/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/pandas/core/indexing.py:517: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

您会看到生成的错误。但在大多数情况下,还是应该在不影响原件的情况下修改原件。现在,先复制:

x = x.copy()
x.iloc[:, 0] += 2  # no warning

您会看到错误被抑制。有趣的是,在垂直子切片上执行类似操作时不会看到相同的行为。我相信 pandas 通过返回完整的独立副本巧妙地处理了这个问题。

【讨论】:

我在创建 data_sub 的地方添加了 2 行代码。我重置了索引,所以我认为它不会再有问题了? @alwaysaskingquestions 对 loc 切片的操作应该反映在原始切片上。所以你得到了警告。我的答案成立。 所以你是说,在我切片数据后,我需要创建另一个副本? @alwaysaskingquestions 是的,如果您正在执行水平切片。见编辑。我不知道还有多少可以说服你! 非常感谢!不不,我没有怀疑你,我只是不清楚该怎么做。但现在我明白了。非常感谢!

以上是关于为啥这段代码会引发 SettingWithCopyWarning? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥受保护的构造函数会在此代码中引发错误?

为啥从未执行过的 Swift 3 代码会引发运行时错误?

为啥此 C# 代码会引发错误:使用未分配的局部变量 'n'

当我从 C# 代码调用导入的 C++ 函数时,为啥会引发 AccessViolationException?

为啥这段代码会进入无限循环? [复制]

为啥从针对任何 CPU 的 C# 项目调用此代码时会引发 System.AccessViolationException?