了解inplace = True


109

pandas库中多次出现改变就地等物体的方式与下面的语句一个选项...

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

我很好奇返回的内容以及inplace=True传递时与传递对象时如何处理该对象inplace=False

所有操作self何时都在修改inplace=True?何时inplace=False立即创建一个新对象,例如new_df = self然后new_df返回?


14
是的,inplace=TruereturnNone inplace=False返回执行了操作的对象的副本。文档对此很清楚,是否有某些与特定部分混淆的东西?SpeficallyIf True, do operation inplace and return None.
EdChum

我正在子类化DataFrame对象,并且使用诸如merge之类的操作似乎无法就地完成它…… self = self.merge(new_df, how='left', on='column2' 我不确定是否可以重新分配自身
Aran Freel

1
您是正确的,DataFrame.merge没有inplace参数。它返回一个DataFrame,因此没有问题重新分配。
JAV

有人还能在资源消耗方面突出使用它的优势吗?
markroxor

2
@markroxor真的不多。在少数情况下,inplace由于您实际上不必返回结果的副本,因此动作可能会更快一些。就是这样。有更多的理由不使用它。
cs95

Answers:


99

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

df.an_operation(inplace=True)

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

df = df.an_operation(inplace=False) 

我是否认为这inplace只是改变现有数据的方法的选择,而不是“重塑”数据的方法的选择?例如,我可以.set_index(inplace = True)将值应用于现有索引,但是不能.reindex(inplace = True),因为这可能会在DataFrame上创建先前数组中不存在的额外行?
ac24

4
该方法.dropna()可以接受inplace=True并且可以绝对重塑数据框,所以不可以。
jorijnsmit

3
您在这里一定要小心。@ ac24实际上或多或少是正确的。虽然dropna返回形状不同的数据帧,但实际上并没有改变底层数据的形状,它只是在其上返回一个掩码(当时inplace=False),这可能导致可怕的SettingWithCopyWarning。仅当不再有对旧值数组的引用时,大熊猫才会根据遮罩进行整形。更好的经验法则是:inplace当操作不需要分配新的值ndarray时可用。
BallpointBen

49

在大熊猫中,inplace = True是否有害?

TLDR;是的,是的。

  • inplace,顾名思义,通常不会阻止创建副本,并且(几乎)从不提供任何性能优势
  • inplace 不适用于方法链接
  • inplace 对于初学者来说是一个常见的陷阱,因此删除此选项将简化API

我不建议设置此参数,因为它的作用很小。请参阅此GitHub问题,其中建议在inplaceapi范围内弃用该参数。

一个普遍的误解是,使用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。出色的开发人员!


1
当然inplace=True不能与链接等一起使用。但是很明显,您可以理解它在概念上的作用。就我个人而言,我发现它可以避免分配工作,这会更清洁-您是否也赞成list.sort从标准库中删除内容?
Chris_Rands

4
我认为这不是一个公平的比较。使用list.sort和sorted有一些明显的好处。其他就地功能也是如此。这里没有真正的好处,方法链接在大熊猫中更为常见,并且无论如何也有计划弃用该论点。
cs95

我还发现它可以避免分配工作:例如,pythonlist.append()也是就地执行的,而pandas df.append则不是(并且就算不支持就位),这也使我无休止。这就是为什么我只想了解真正的好处是为什么-除了避免分配之外,使用list.sort与sorted相比有哪些明显的好处?否则,我认为这是真正的好处-我能够避免分配,而我个人认为它更具可读性。
sdbbs

1
@sdbbslist.append()追加到现有列表。df.append复制数据(与是否有5行或5百万无关),然后向副本中添加新行,然后返回它。您认为更有意义的是什么?至于df.append,尽可能避免。我认为这不是争辩inplace = True的好例子,我什至不认为该函数在API中占有一席之地。
cs95

46

我使用它的方式是

# 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

5
嗨@Nabin,对于任何从事Pandas和Numpy工作的人来说,这太清楚了:-)
Vetrivel PS

6

inplace参数:

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

Pandas与一般的手段:

1.熊猫创建原始数据的副本

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

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

4. ...删除副本。

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

1.您的代码将更难调试(实际上,SettingwithCopyWarning表示警告您可能出现的问题)

2.与方法链冲突


因此,甚至在某些情况下我们应该使用它吗?

绝对可以。如果我们使用熊猫或任何工具处理庞大的数据集,我们很容易面对这样的情况,即一些大数据会消耗我们的整个内存。为了避免这种不良影响,我们可以使用诸如方法链接之类的一些技术:

(
    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倍的原始数据内存消耗。

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


定论:

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


2

将其保存到相同的变量

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


1

当尝试使用函数对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}

0

inplace=True 是否使用取决于您是否要更改原始df。

df.drop_duplicates()

将仅查看丢弃的值,而不会对df进行任何更改

df.drop_duplicates(inplace  = True)

将删除值并更改df。

希望这可以帮助。:)


0

inplace=True使功能不纯。它更改原始数据框并返回无。在这种情况下,您会中断DSL链。由于大多数数据框功能都返回一个新的数据框,因此可以方便地使用DSL。喜欢

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

inplace=True返回值为None的函数调用,并且DSL链断开。例如

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

会抛出 NoneType object has no attribute 'rename'

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

通常,inplace=True除非有特殊原因,否则请勿使用。当您必须编写类似的重新分配代码时df = df.sort_values(),请尝试将函数调用附加到DSL链中,例如

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

提供具有正确格式的准确工作代码确实可以帮助用户更快地理解您的答案。要求您做同样的事情。我不是熊猫专家,所以无法重新格式化你的答案,但它的极力推荐,
阿南德维迪

0

就我在大熊猫方面的经验而言,我想回答一下。

'inplace = True'参数代表数据帧必须永久更改,例如。

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

更改相同的数据框(因为这只大熊猫在索引中找到NaN条目并将其删除)。如果我们尝试

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

熊猫显示了我们进行了更改的数据框,但不会修改原始数据框“ df”。


0

如果您不使用inplace = True或使用inplace = False,则基本上可以得到一个副本。

因此,例如:

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

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

然后:

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

将使testdf2成为副本。值将全部相同,但排序将颠倒,您将拥有一个独立的对象。

然后在另一列中,说出LongMA,您可以:

testdf2.LongMA = testdf2.LongMA -1

testdf中的LongMA列将保留原始值,而testdf2列将减少值。

随着计算链的增长以及数据帧的副本具有其自己的生命周期,跟踪差异至关重要。


0

是的,在Pandas中,我们有很多具有参数的函数,inplace但默认情况下将其分配给False

因此,当您执行df.dropna(axis='index', how='all', inplace=False)此操作时,它认为您不想更改orignial DataFrame,因此它为您创建具有所需更改的新副本

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

然后,这等效于明确地说,我不需要新的副本,DataFrame而是对给定的内容进行更改DataFrame

这迫使Python解释器不要创建新的DataFrame

但是您也可以inplace通过将结果重新分配给原始DataFrame来避免使用参数

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.