Python Pandas SettingWithCopyWarning 副本与新对象
Posted
技术标签:
【中文标题】Python Pandas SettingWithCopyWarning 副本与新对象【英文标题】:Python Pandas SettingWithCopyWarning copies vs new objects 【发布时间】:2016-10-31 10:19:08 【问题描述】:我正在使用通过子设置前一个创建的数据框“副本” - 见下文:
import random
import pandas as pd
df = pd.DataFrame('data':list(random.sample(range(10,100),25)))
df_filtered = df.query('data > 20 and data < 80')
df_filtered.rename(columns='data':'observations',inplace=True)
问题是,当调用重命名方法时,我收到一个 SettingWithCopy 警告,据我了解,这意味着我正在对原始(在本例中为 df)对象的副本进行操作。警告文本是:“试图在 DataFrame 中的切片副本上设置值”
我发现this question 使用不同的子集化方法得到了回答。我自己更喜欢 Dataframe.query() 方法(语法方面)。有没有办法可以使用 .query() 方法而不是我链接的问题中建议的方法来创建新的 Dataframe 对象?我已经尝试了 iloc 的一些选项,但到目前为止还没有成功。
【问题讨论】:
你的目标是什么?你想要一个具有独立值的 DF(副本)吗?注意:这会花费你额外的内存。 在这个例子中是的,我的意图是让 df_filtered 成为一个完全不同于 df 的独立对象。我意识到这两个对象都将在内存中,但对于这个例子来说没关系。 【参考方案1】:您始终可以通过在过滤后的数据帧上调用 .copy()
来显式制作副本。具体来说,替换
df_filtered = df.query('data > 20 and data < 80')
与
df_filtered = df.query('data > 20 and data < 80').copy()
这是否消除了警告?
【讨论】:
这也解决了问题。因此,如果我不调用复制函数,当您对数据框(而不是新对象)进行子集化时,pandas 会创建不同类型的对象吗?我已经尝试查看文档,但我还不明白发生了什么……我最担心的是我想确保它正在做我想做的事情。 如果不调用.copy()
,df_filtered
可能是原始df
的视图——直到运行时才能知道。这就是你收到警告的原因。 Pandas 代码中有很多防御性复制,但它并不通用——很多时候你确实想要一个视图而不是一个副本。
感谢阿尔贝托的信息!您知道 Max 建议的方法(直接使用等号运算符而不是使用 inplace 参数完成赋值)的行为方式是否与显式调用 copy() fn 相同?只是想了解我是否应该注意更多细微差别的行为:)
是的,如果没有 inplace=True
,您将创建一个新的数据框,因此 MaxU 建议的分配最终会为您提供与我建议的完全相同的结果。【参考方案2】:
试试这个而不是使用inplace=True
:
In [12]: df_filtered = df.query('data > 20 and data < 80')
In [13]: df_filtered = df_filtered.rename(columns='data':'observations')
.rename() 函数返回一个新对象,因此您可以简单地用返回的新 DF 覆盖您的 DF
如果您使用inplace
,则会发生以下情况
来自docs:
就地:布尔值,默认为False
是否返回一个新的DataFrame。如果为 True,则忽略 copy 的值。
返回:
重命名:DataFrame(新对象)
PS 基本上你应该尽量避免使用inplace=True
而使用df = df.function(...)
技术
【讨论】:
谢谢 Max - 警告消失了,但是当 inplace 参数不起作用时,为什么像这样强制分配?我想我可以习惯这一点,但我想了解为什么这对我尝试过的东西有效……有什么想法吗? 为什么要“避免使用 inplace=True 而使用 df = df.function(...)”以上是关于Python Pandas SettingWithCopyWarning 副本与新对象的主要内容,如果未能解决你的问题,请参考以下文章