【问题标题】:Preventing SettingWithCopy warning, proper use of views/copies of Pandas dataframe防止 SettingWithCopy 警告,正确使用 Pandas 数据框的视图/副本
【发布时间】:2017-02-08 00:50:57
【问题描述】:

在更改从另一个数据帧的切片创建的数据帧时,我是否应该始终使用 .copy() 方法显式生成副本?否则,我会收到 SettingWithCopy 警告。但是,在这种情况下,它并没有导致任何麻烦;原始数据框未更改。

>>> import pandas as pd
>>> df = pd.DataFrame([[6,3,2],[4,3,2],[5,4,2],[4,3,5]], columns=['a', 'b', 'c'])
>>> df
   a  b  c
0  6  3  2
1  4  3  2
2  5  4  2
3  4  3  5
>>> df2 = df.loc[df.a<6, :]
>>> df2.loc[df2.b==3, 'b'] = 99
/usr/lib/python3/dist-packages/pandas/core/indexing.py:117: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  self._setitem_with_indexer(indexer, value)
__main__:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
>>> df
   a  b  c
0  6  3  2
1  4  3  2
2  5  4  2
3  4  3  5
>>> df2
   a   b  c
1  4  99  2
2  5   4  2
3  4  99  5

或者,如果我执行以下操作,我不会收到任何警告。

>>> df2 = df.loc[df.a<6, :].copy()
>>> df2.loc[df2.b==3, 'b'] = 99
>>> df2
   a   b  c
1  4  99  2
2  5   4  2
3  4  99  5
>>> df
   a  b  c
0  6  3  2
1  4  3  2
2  5  4  2
3  4  3  5

后者更好吗? (因此我没有收到警告)。凭什么?是因为我确信 df2 是副本,因此无法更改原始数据帧 df?

【问题讨论】:

  • 您确定这两个选项的作用完全相同吗?
  • 好吧,df299 插入到两个实现的正确位置。这是你的意思吗?

标签: python python-3.x pandas


【解决方案1】:

如果用户对命令的解释方式存在歧义,则会出现 SettingWithCopyWarning。在第一种情况下,pandas 很清楚应该将值分配给df2。但是,尚不清楚用户是否期望值分配传播到df 本身,这就是引发警告的原因。在内部,pandas 使用数据帧的 _is_copy 属性来跟踪这一点。创建df2 时,_is_copy 属性存储对df 的弱引用。

In [1]: import pandas as pd

In [2]: df = pd.DataFrame([[6,3,2],[4,3,2],[5,4,2],[4,3,5]], columns=['a', 'b', 'c'])

In [3]: df2 = df.loc[df.a<6, :]

In [4]: df2._is_copy
Out[4]: <weakref at 0x7f0dae5a3770; to 'DataFrame' at 0x7f0daef08850>

在第二种情况下,df2 被显式创建为 df 的副本,因此 pandas 不会将弱引用存储到 df

In [5]: df2 = df.loc[df.a<6, :].copy()

In [6]: df2._is_copy

In [7]: print(df2._is_copy)
None

您对df2 所做的任何操作都不会影响其他数据帧,因此值分配没有歧义,因此无需引发 SettingWithCopyWarning。

来源:

【讨论】:

    猜你喜欢
    • 2021-05-25
    • 1970-01-01
    • 2019-12-20
    • 2019-04-17
    • 2021-04-26
    • 1970-01-01
    • 1970-01-01
    • 2016-12-14
    • 1970-01-01
    相关资源
    最近更新 更多