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 中发布

仅在出现错误时创建 Python 日志文件(使用日志记录模块)

无法加载视图状态。仅在 IE 中发生错误

从 Python 脚本中请求 UAC 提升?

仅在 Rails 中搭建视图文件。可能的?