深入探讨何时应该在 Pandas 函数中使用 Inplace 参数以及为什么不使用它?

Ogh*_*hli 1 python dataframe pandas

在操作数据帧时,在 Pandas 函数中使用就地参数可能是很常见的。

Inplace是在不同函数中使用的参数。一些函数中使用 inplace 作为属性,例如set_index(), dropna(), fillna(), reset_index(), drop(), replace()等等。该属性的默认值为False,它返回对象的副本。

我想详细了解什么时候在 pandas 函数中使用是好的做法inplace,什么时候也不应该这样做,以及原因。您能否在示例中进行演示以供参考,因为这个问题在使用 pandas 函数时很常见。

例如:

df.drop(columns=[your_columns], inplace=True)

在这种情况下,建议使用 inplace 和 drop 。另外,如果某些变量喜欢list依赖于数据框。就地更改它会影响依赖于它的其他变量的结果。另一个问题是在 pandas 数据帧上使用就地阻止方法链接。

Mik*_*son 7

我会举一些例子,但更好的方式是从风格来看待它。

首先,对于任何生产代码或可以以任意并行方式运行的代码,您不想更改任何内容。

函数式编程和面向对象编程之间存在一个主要的哲学差异: 函数式编程没有副作用。这意味着什么?这意味着如果我有一个函数或方法,让我们举df.drop()一个具体的例子,那么drop以纯函数的方式使用只会返回一个结果,它不会做任何其他事情。

让我们制作一个数据框:

>>> df = pd.DataFrame({"name": ["Alice", "Bob", "Candi"],
"job": ["CFO", "Accountant", "Developer"],
"department": ["Executive", "Accounting", "Product"]})
>>> df
    name         job  department
0  Alice         CFO   Executive
1    Bob  Accountant  Accounting
2  Candi   Developer     Product
Run Code Online (Sandbox Code Playgroud)

无副作用 (inplace=False

现在,如果我drop功能方式调用,所发生的只是返回一个带有缺失列的新数据帧

>>> df.drop(columns = "job", inplace=False)
    name  department
0  Alice   Executive
1    Bob  Accounting
2  Candi     Product
Run Code Online (Sandbox Code Playgroud)

请注意,我正在返回结果,即数据帧。明确地说,我可以这样做:

>>> new_df = df.drop(columns="job", inplace=False)
>>> new_df
    name  department
0  Alice   Executive
1    Bob  Accounting
2  Candi     Product
Run Code Online (Sandbox Code Playgroud)

请注意,new_df已分配给该方法的返回结果drop

有副作用 ( inplace=True)

>>> df.drop(columns="job", inplace=True)
>>> 
Run Code Online (Sandbox Code Playgroud)

请注意,没有返回任何内容!这个方法的返回值实际上是None

但确实发生了一些事情:

>>> df
    name  department
0  Alice   Executive
1    Bob  Accounting
2  Candi     Product
Run Code Online (Sandbox Code Playgroud)

如果我请求数据框,我们可以看到它df实际上已更改,因此该job列丢​​失了。但这完全是一个副作用,而不是回报

为了证明没有返回任何内容,让我们再试一次(使用不同的列,原因如下所述)并将该方法的结果分配inplace给一个新变量:

>>> not_much = df.drop(columns="name", inplace=True)
>>> type(not_much)
<class 'NoneType'>
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,变量not_much是 of NoneType,这意味着None已返回。

哲学 - 或者,“何时使用或不使用”

多年来,软件工程发生了变化,并行活动现在变得更加普遍。如果您在 Spark 上运行大数据作业,或者即使您在单台笔记本电脑上运行 pandas,您也可以将任务配置为在多个进程上异步运行多线程(如 Map-Reduce 作业等)。

由于这种并行操作,您通常不知道首先会发生什么,然后会发生什么。您需要尽可能多的操作,要么不更改状态,要么以原子方式更改状态。

现在让我们重新审视一下df.drop,重复多次。想象一下,您有一项受网络限制的大数据作业(通常是这种情况),您只需要求 10 台机器执行相同的任务,然后您接受最先返回答案的机器的答案。这是处理网络不一致的常见方法。

Inplace

>>> df
    name         job  department
0  Alice         CFO   Executive
1    Bob  Accountant  Accounting
2  Candi   Developer     Product
>>> df.drop(columns="job", inplace=True)
>>> df.drop(columns="job", inplace=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    raise KeyError(f"{list(labels[mask])} not found in axis")
KeyError: "['job'] not found in axis"
>>> 
Run Code Online (Sandbox Code Playgroud)

我刚刚运行了两次相同的工作,并得到了不同的答案,其中一个导致了错误。这对于并行作业运行来说并不好。

不是Inplace

>>> new_df = df.drop(columns="job", inplace=False)
>>> new_df
    name  department
0  Alice   Executive
1    Bob  Accounting
2  Candi     Product
>>> new_df = df.drop(columns="job", inplace=False)
>>> new_df
    name  department
0  Alice   Executive
1    Bob  Accounting
2  Candi     Product
Run Code Online (Sandbox Code Playgroud)

无论上面的代码运行多少次,new_df都将始终等于相同的事情。

何时使用其中一种或另一种

我永远不会使用它inplace=True,除非它是在一次性 Jupyter 笔记本、家庭作业或远离生产环境的其他东西中。

最后说明

我开始谈论“函数式与面向对象”。这就是它的框架,但我不喜欢这种比较,因为它引发了激烈的争论,而面向对象不一定有副作用。

只是函数式不能有副作用,而面向对象常常有副作用。

我更喜欢说“副作用与无副作用”。这个选择很简单:只要有可能,就始终防止副作用,但要认识到这并不总是可能的(尽管Haskel 是这么建议的)。