Python 视图与复制错误希望我仅在脚本中使用 .loc
Posted
技术标签:
【中文标题】Python 视图与复制错误希望我仅在脚本中使用 .loc【英文标题】:Python view vs copy error wants me to use .loc in script only 【发布时间】:2019-03-17 09:08:40 【问题描述】:我正在运行一个长脚本,其中包含一个数据框df
。随着脚本运行,逐列构建和修改df
,我在命令行中一遍又一遍地收到此错误:
试图在 DataFrame 的切片副本上设置一个值。尝试 使用 .loc[row_indexer,col_indexer] = value 代替请参阅注意事项 文档: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
但是它会打印出导致警告的行,并且看起来不会有问题。像下面这样的行会触发它(每行单独触发):
df['ZIP_DENS'] = df['ZIP_DENS'].astype(str)
df['AVG_WAGE'] = df['AVG_WAGE'].astype(str).apply(lambda x:x if x != 'nan' else 'unknown')
df['TERM_BIN'] = df['TERMS'].map(terms_dict)
df['LOSS_ONE'] = 'T_'+ df['TERM'].astype(str) +'_C_'+ df['COMP'].astype(str) + df['SIZE']
# this one's inside a loop:
df[i + '_BIN'] = df[i + '_BIN'].apply(lambda x:x if x != 'nan' else 'unknown')
我在数据帧上进行了一些突变示例。现在,这个警告刚刚开始出现,但我无法在解释器中重现这个问题。当我打开终端时,我会尝试这样的事情,但它没有给我任何警告:
import pandas as pd
df = pd.DataFrame([list('ab'),list('ef')],columns=['first','second'])
df['third'] = df[['first','second']].astype('str')
我是否遗漏了什么,我不了解此警告试图告诉我的 DataFrames 的性质?您是否认为我在脚本开头对这个数据框做了一些事情,然后对象上的所有后续突变都是视图或它的副本上的突变,或者正在发生类似的奇怪事情?
【问题讨论】:
我看不出你的代码有什么问题。请记住,这只是一个警告。这并不意味着有任何误判。 我猜你的代码上游某处有类似df = somedf[list_of_rows, list_of_columns]
的声明。所以现在 df 指向一个切片,即 somedf 内存中的位置,而不是一个视图,即您使用 .loc 获得的切片中的值。因此,现在每次在这个新的 df 中设置任何内容时,都会收到警告消息。我建议只使用 loc 代替 - 它在大多数情况下是相似的语法。或者,您可以在进行初始分配时写 df = somedf[list_of_rows, list_of_columns].copy()
。
【参考方案1】:
正如我在评论中提到的,可能的问题是在您的代码上游某处,您将其他一些pd.DataFrame
的一部分分配给了df
。
这是造成混淆的常见原因,在Warning
提到的链接中的why-does-assignment-fail-when-using-chained-indexing 下也有解释。
一个最小的例子:
data = pd.DataFrame('a':range(7), 'b':list('abcccdb'))
df = data[data.a % 2 == 0] #making a subselection of the DataFrame
df['b'] = 'b'
/home/user/miniconda3/envs/myenv/lib/python3.6/site-packages/ipykernel_launcher.py:1: SettingWithCopyWarning:试图在一个副本上设置一个值 从 DataFrame 切片。尝试使用 .loc[row_indexer,col_indexer] = 取而代之的价值
请参阅文档中的注意事项: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy """启动 IPython 内核的入口点。
注意这部分:
df = data[data.a % 2 == 0] #making a subselection of the DataFrame
df['b'] = 'b'
也可以这样重写:
data[data.a % 2 == 0]['b'] = 'b' #obvious chained indexing
df = data[data.a % 2 == 0]
该位的正确写法如下:
data = pd.DataFrame('a':range(7), 'b':list('abcccdb'))
df = data.loc[data.a % 2 == 0].copy() #making a copy of the subselection
df.loc[:,'b'] = 'b'
【讨论】:
你说得对,我将其追溯到这一行df[new_col_name] = temp[new_col_name]
所以然后我用合并替换它并且它工作正常。 temp = temp.drop([metric, column], axis=1); df = df.merge(temp, indicator=False, left_index=True, right_index=True)
很高兴能帮上忙 - 我知道这不太直观!以上是关于Python 视图与复制错误希望我仅在脚本中使用 .loc的主要内容,如果未能解决你的问题,请参考以下文章
当我仅使用脚本名称在 Windows 上运行 Python 脚本时无法重定向输出
AngularJS 的 CORS 错误仅在 FireFox 中发布