问题描述
r = df_1[~df_1isin(
df_2.to_dict('list')).all(1)]
r['is_sent'] = pd.Series(False).bool()
目的是缩小两个数据框之间的搜索范围,然后我想添加一个新列(pd.series)并将这些发现设置为 false。这符合我的意图,但返回一条消息:
“正在尝试在 DataFrame 中切片的副本上设置值。 尝试使用 .loc[row_indexer,col_indexer] = value 代替"
谁能解释一下这是什么意思,并举例说明什么是正确的方法?
解决方法
这个问题是对 DataFrame 进行切片会在切片和原始 DataFrame 之间创建一个 weakref
。当你做作业时,这会在下一行触发警告。
import pandas as pd
df = pd.DataFrame([0,1,2])
r = df[df.isin([1]).all(1)]
r['new_col'] = False
#<ipython-input-210-d5f9bda478c4>:9: SettingWithCopyWarning: ...
您可以使用内置方法 ._is_copy
df = pd.DataFrame([0,2])
r = df[df.isin([1]).all(1)]
r._is_copy
#<weakref at 0x142b10e00; to 'DataFrame' at 0x14361ed00>
打破这种情况的最简单方法是使用 .copy()
强制深度复制,以便 r
与 df
没有关系,这将消除警告。>
r = df[df.isin([1]).all(1)].copy()
r._is_copy
#None
r['new_col'] = False
# No warning!
最后,这个警告经常似乎被击中或错过,但这是因为许多熊猫操作返回一个新对象,所以如果切片和分配很可能这些操作本身会破坏弱引用,从而阻止警告。例如,像乘以 2 这样的简单操作会创建一个新对象,而您不会收到警告。
df = pd.DataFrame([0,2])
r = df[df.isin([1]).all(1)]
print(r._is_copy)
#<weakref at 0x13e6ad0e0; to 'DataFrame' at 0x1436227c0>
r = r*2 # Breaks the reference
print(r._is_copy)
# None
r['new_col'] = False
# No warning!