对熊猫的理解

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,但没有,考虑 方法不能在熊猫数据框架上工作而不是。

234123 次浏览

当传递 inplace=True时,数据被重命名(它什么也不返回) ,因此您可以使用:

df.an_operation(inplace=True)

当传递 inplace=False时(这是默认值,因此没有必要) ,执行操作并返回对象的一个副本,因此您将使用:

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

在熊猫中,替代 = 真被认为是有害的,还是无害的?

是的,是的。

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

上面的痛点对于初学者来说是常见的陷阱,因此删除这个选项将简化 API。


我不建议设置这个参数,因为它没有什么用处。参见 GitHub 的问题,它建议在 api 范围内不推荐使用 inplace参数。

使用 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。干得好 Devs!

使用 inplace=True取决于您是否希望对原始 df 进行更改。

df.drop_duplicates()

将只创建删除值的视图,而不对 df 进行任何更改

df.drop_duplicates(inplace  = True)

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

希望这个能帮上忙。)

inplace=True使函数不纯。它更改原始数据框并返回 Nothing。在这种情况下,您将中断 DSL 链。 因为大多数数据框架函数返回一个新的数据框架,所以可以方便地使用 DSL

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

函数调用与 inplace=True返回无和 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()...

至于我的熊猫经验,我想回答。

“ inplace = True”参数表示数据框架必须使更改永久化 例如。

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

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

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

熊猫显示的数据框架与我们所做的修改,但不会修改原来的数据框架’df’。

inplace参数:

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

一般指:

熊猫创建原始数据的副本

对它做了一些计算

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

删除副本。

正如你可以在我下面的回答中读到的,我们仍然有很好的理由使用这个参数,即 inplace operations,但是我们应该尽量避免它,因为它会产生更多的问题,如:

1. 您的代码将更难调试(实际上 设置与拷贝警告代表警告您可能出现的问题)

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参数,除非您不使用大数据,并且在仍然使用它的情况下了解其可能的问题。

如果没有使用 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将具有分类值。

随着计算链的增长以及数据框架的副本有自己的生命周期,跟踪差异非常重要。

当尝试使用函数对熊猫数据框进行更改时,如果我们想要提交对数据框的更改,我们使用‘ inplace = True’。 因此,下面代码中的第一行将“ df”中第一列的名称更改为“评分”。如果我们想要看到结果数据库,我们需要调用数据库。

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}

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

所以,当你做 df.dropna(axis='index', how='all', inplace=False)它认为你不想改变原来的 DataFrame,因此它代替 创建一个新的副本为你所需要的改变。

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

那么它等同于明确地说我不想要一个新的副本 取而代之的是对给定的 DataFrame进行更改

这迫使 Python 解释器到 没有创建一个新的 DataFrame

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

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