Python Pandas - 了解inplace = True

Ara*_*eel 53 python in-place pandas

pandas库中很多次都有一个选项来更改对象,例如使用以下语句...

df.dropna(axis='index', how='all', inplace=True)
Run Code Online (Sandbox Code Playgroud)

我很好奇返回的内容以及inplace=True传递对象时的处理方式inplace=False.

正在修改的所有操作selfinplace=True?什么时候inplace=False立即创建一个新对象new_df = self,然后new_df返回?

cs9*_*s95 71

在熊猫中, inplace = True 是否被认为有害?

TLDR;是的,是的。

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

上述痛点是初学者的常见陷阱,因此删除此选项将简化 API。


我不建议设置这个参数,因为它没什么用。请参阅此 GitHub 问题该问题建议在inplaceapi-wide 范围内弃用该参数。

一个常见的误解是使用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
Run Code Online (Sandbox Code Playgroud)

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

好像上面描述的问题还不够,inplace=True阻碍了方法链接。对比工作

result = df.some_function1().reset_index().some_function2()
Run Code Online (Sandbox Code Playgroud)

temp = df.some_function1()
temp.reset_index(inplace=True)
result = temp.some_function2()
Run Code Online (Sandbox Code Playgroud)

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


另一个支持声明是set_axis最近更改了 API,以便将inplace默认值从 True 切换为 False。见GH27600。伟大的工作开发者!

  • 当然,“inplace=True”不适用于链接等,但很明显,您从概念上理解它在做什么。就我个人而言,我发现避免分配更干净一些 - 您是否也赞成从标准库中删除“list.sort”等? (5认同)
  • 我认为这是一个不公平的比较。与排序相比,使用 list.sort 有一些明显的好处。其他就地功能也是如此。这里没有真正的好处,方法链接在 pandas 中更为常见,并且无论如何都有计划弃用此参数。 (5认同)
  • 人们使用 inplace=True 的原因是因为 pandas api 不直观,因为“就地”操作是预期/期望的行为。例如,为什么重命名列或重置索引的简单情况应该返回一个新对象?没有人愿意一遍又一遍地将这些操作重新分配回同一个变量,这看起来很糟糕。 (5认同)
  • 还有一个关于内存消耗的问题。来自线程 /sf/answers/4153504421/ 的答案表示,在内存情况下,“inlace”效率更高。是真的吗(我对此表示怀疑)? (2认同)

ECH*_*ECH 60

如果inplace=True通过,该数据被重命名到位(它没有返回值),所以你会使用:

df.an_operation(inplace=True)
Run Code Online (Sandbox Code Playgroud)

inplace=False传递(这是默认值,所以没有必要),执行操作,并返回该对象的副本,所以你会使用:

df = df.an_operation(inplace=False) 
Run Code Online (Sandbox Code Playgroud)

所以:

if inplace == False:
    Assign your result to a new variable
else
    No need to assign
Run Code Online (Sandbox Code Playgroud)

  • 方法`.dropna()`接受`inplace = True`并且绝对可以重塑数据帧,所以没有. (4认同)
  • 在这里你必须小心。@ac24 实际上或多或少是正确的。虽然 `dropna` 返回一个不同形状的数据帧,它实际上并没有重塑底层数据——它只是返回一个掩码(当 `inplace=False` 时),这可能导致可怕的 `SettingWithCopyWarning`。只有当不再有对旧值数组的引用时,pandas 才会根据掩码重塑形状。一个更好的经验法则是:当操作不需要分配新的支持 ndarray 值时,`inplace` 可用。 (3认同)

Nab*_*bin 31

我使用它的方式是

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

要么

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

结论:

 if inplace is False
      Assign to a new variable;
 else
      No need to assign
Run Code Online (Sandbox Code Playgroud)

  • @Nabin大家好,对从事Pandas和Numpy的任何人来说,这样的方法太清楚了:-) (3认同)

Gee*_*ode 7

inplace参数:

df.dropna(axis='index', how='all', inplace=True)
Run Code Online (Sandbox Code Playgroud)

in Pandasand in 一般是指:

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

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

3. ... 将结果分配给原始数据。

4. ...删除副本。

正如你在我的答案其余阅读下面的进一步,我们还可以有充分的理由来使用此参数即inplace operations,但如果能,我们应该避免,因为它产生更多的问题,如:

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

2.与方法链冲突


那么甚至还有什么时候我们应该使用它呢?

肯定是的。如果我们使用 Pandas 或任何工具来处理庞大的数据集,我们很容易面临这样的情况,即一些大数据会消耗我们的整个内存。为了避免这种不必要的影响,我们可以使用一些技术,如方法链

(
    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"]]
)
Run Code Online (Sandbox Code Playgroud)

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

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


定论:

避免使用inplace参数,除非您不使用大量数据,并且在仍然使用它的情况下注意其可能出现的问题。

  • 您能否解释一下为什么我们在使用 chainig 方法时“此操作后将消耗 2 倍原始数据内存”?我明白为什么我们在计算时需要 x2,但不明白为什么我们之后仍然使用 x2 (2认同)