了解 pandas 中的 inplace=True

Understanding inplace=True in pandas

pandas 库中,很多时候有一个选项可以就地更改对象,例如使用以下语句...

df.dropna(axis='index', how='all', inplace=True)

我很好奇在传递 inplace=True 时与传递 inplace=False.

时返回的是什么以及如何处理对象

inplace=True时所有操作都修改self吗?而当inplace=False是立即创建一个新对象如new_df = self然后返回new_df

inplace=True 被传递时,数据被重命名(它 returns 什么都没有),所以你会使用:

df.an_operation(inplace=True)

当传递 inplace=False 时(这是默认值,因此不是必需的),执行操作和 returns 对象的副本,因此您可以使用:

df = df.an_operation(inplace=False) 

我的使用方式是

# Have to assign back to dataframe (because it is a new copy)
df = df.some_operation(inplace=False) 

或者

# No need to assign back to dataframe (because it is on the same copy)
df.some_operation(inplace=True)

结论:

 if inplace is False
      Assign to a new variable;
 else
      No need to assign

保存到同一个变量

data["column01"].where(data["column01"]< 5, inplace=True)

保存到一个单独的变量

data["column02"] = data["column01"].where(data["column1"]< 5)

但是,您始终可以覆盖变量

data["column01"] = data["column01"].where(data["column1"]< 5)

仅供参考:默认 inplace = False

In pandas, is inplace = True considered harmful, or not?

TLDR;是的,是的。

  • inplace,与名称所暗示的相反,通常不会阻止创建副本,并且(几乎)从不提供任何性能优势
  • inplace 不适用于方法链接
  • inplace 如果在 DataFrame 列上使用,可能会导致 SettingWithCopyWarning,并且可能会阻止操作进行,从而导致代码中难以调试的错误

以上痛点是新手常犯的坑,去掉这个选项会简化API。


我不建议设置这个参数,因为它没有什么用处。请参阅 this GitHub issue,其中建议 inplace 参数在 api 范围内弃用。

一个常见的误解是使用 inplace=True 会产生更高效或优化的代码。实际上,使用 inplace=True 绝对没有性能优势 。就地和非就地版本都会创建数据副本无论如何,就地版本会自动分配回副本。

inplace=True 是初学者常犯的错误。例如,它可以 触发 SettingWithCopyWarning:

df = pd.DataFrame({'a': [3, 2, 1], 'b': ['x', 'y', 'z']})

df2 = df[df['a'] > 1]
df2['b'].replace({'x': 'abc'}, inplace=True)
# SettingWithCopyWarning: 
# A value is trying to be set on a copy of a slice from a DataFrame

使用 inplace=True 在 DataFrame 列上调用函数 可能有效也可能无效 。当涉及链式索引时尤其如此。

似乎上述问题还不够,inplace=True阻碍了方法链接。对比

的工作方式
result = df.some_function1().reset_index().some_function2()

相对于

temp = df.some_function1()
temp.reset_index(inplace=True)
result = temp.some_function2()

前者有助于更好的代码组织和可读性。


另一个支持性的说法是 set_axis 的 API 最近发生了变化,inplace 默认值从 True 变为 False。参见 GH27600。开发者干得好!

inplace=True 的使用取决于是否要对原始 df 进行更改。

df.drop_duplicates()

只会查看删除的值,不会对 df 进行任何更改

df.drop_duplicates(inplace  = True)

将删除值并对 df 进行更改。

希望这对您有所帮助。:)

inplace=True 使函数不纯。它改变了原始数据帧和 returns None。在这种情况下,您会破坏 DSL 链。 因为大多数dataframe函数return一个新的dataframe,你可以方便地使用DSL。喜欢

df.sort_values().rename().to_csv()

使用 inplace=True returns None 的函数调用和 DSL 链被破坏。例如

df.sort_values(inplace=True).rename().to_csv()

会抛出NoneType object has no attribute 'rename'

与 python 的内置排序和排序类似。 lst.sort() returns Nonesorted(lst) returns 一个新列表。

一般情况下,除非有特殊原因,否则不要使用 inplace=True。当您必须编写 df = df.sort_values() 之类的重新分配代码时,请尝试在 DSL 链中附加函数调用,例如

df = pd.read_csv().sort_values()...

根据我在pandas的经验,我想回答一下。

'inplace=True'参数表示数据框必须永久更改 例如。

    df.dropna(axis='index', how='all', inplace=True)

更改相同的数据帧(因为这 pandas 在索引中找到 NaN 条目并删除它们)。 如果我们尝试

    df.dropna(axis='index', how='all')

pandas 显示我们所做更改的数据框,但不会修改原始数据框 'df'。

inplace参数:

df.dropna(axis='index', how='all', inplace=True)

Pandas 中一般表示:

1. Pandas 创建原始数据的副本

2. ...对其进行一些计算

3. ...将结果赋给原始数据。

4. ...删除副本。

您可以在下面进一步阅读我的其余回答,我们仍然可以有充分的理由使用此参数,即 inplace operations,但我们应该避免如果可以的话,因为它会产生更多问题,如:

1. 你的代码将更难调试(实际上 SettingwithCopyWarning 代表警告你这个可能的问题)

2. 与方法链冲突


那么还有什么时候应该用到的呢?

绝对是。如果我们使用pandas或任何处理庞大数据集的工具,我们很容易面临一些大数据会占用我们全部内存的情况. 为了避免这种不良影响,我们可以使用一些技术,例如 method chaining:

(
    wine.rename(columns={"color_intensity": "ci"})
    .assign(color_filter=lambda x: np.where((x.hue > 1) & (x.ci > 7), 1, 0))
    .query("alcohol > 14 and color_filter == 1")
    .sort_values("alcohol", ascending=False)
    .reset_index(drop=True)
    .loc[:, ["alcohol", "ci", "hue"]]
)

这使得我们的代码更紧凑(尽管也更难解释和调试)并且消耗更少的内存,因为链接的方法与其他方法的返回值一起工作,因此只产生 一个副本 输入数据。我们可以清楚地看到,在这个操作之后我们将有 2 x 原始数据 内存消耗。

或者我们可以使用 inplace 参数(虽然也更难解释和调试)我们的内存消耗将是 2 x 原始数据,但我们的内存消耗在此之后操作仍然是 1 x 原始数据,如果有人在处理庞大的数据集时确切地知道这是一个很大的好处。


最终结论:

避免使用 inplace 参数,除非您不处理大量数据,并注意在继续使用它时可能出现的问题。

如果您不使用 inplace=True 或使用 inplace=False,您基本上会取回一份副本。

例如:

testdf.sort_values(inplace=True, by='volume', ascending=False)

将改变结构,数据按降序排列。

然后:

testdf2 = testdf.sort_values( by='volume', ascending=True)

将使 testdf2 成为一个副本。所有的值都相同,但排序相反,您将拥有一个独立的对象。

然后给出另一列,说龙马你做:

testdf2.LongMA = testdf2.LongMA -1

testdf 中的 LongMA 列将具有原始值,而 testdf2 将具有减值后的值。

随着计算链的增长和数据帧的副本有自己的生命周期,跟踪差异很重要。

当尝试使用函数对 Pandas 数据框进行更改时,如果我们想将更改提交到数据框,我们会使用 'inplace=True'。 因此,以下代码的第一行将 'df' 中第一列的名称更改为 'Grades'。如果我们想看到生成的数据库,我们需要调用数据库。

df.rename(columns={0: 'Grades'}, inplace=True)
df

当我们不想提交更改而只是打印生成的数据库时,我们使用 'inplace=False'(这也是默认值)。因此,实际上,在不更改原始数据库的情况下打印了包含已提交更改的原始数据库的副本。

为了更清楚,以下代码做同样的事情:

#Code 1
df.rename(columns={0: 'Grades'}, inplace=True)
#Code 2
df=df.rename(columns={0: 'Grades'}, inplace=False}

是的,在 Pandas 中我们有很多函数都有参数 inplace 但默认情况下它被分配给 False.

因此,当您执行 df.dropna(axis='index', how='all', inplace=False) 时,它认为您不想更改原始 DataFrame,因此它 创建一个新副本 您进行了必要的更改。

但是,当您将 inplace 参数更改为 True

Then it is equivalent to explicitly say that I do not want a new copy of the DataFrame instead do the changes on the given DataFrame

这会强制 Python 解释器 而不是 创建一个新的 DataFrame

但是您也可以通过将结果重新分配给原始 DataFrame

来避免使用 inplace 参数

df = df.dropna(axis='index', how='all')