gpt4 book ai didi

python - pandas df.apply 意外更改数据框

转载 作者:太空狗 更新时间:2023-10-29 20:30:59 28 4
gpt4 key购买 nike

根据我的理解,pandas.DataFrame.apply 不会就地应用更改,我们应该使用它的返回对象来保存任何更改。但是,我发现了以下不一致的行为:

为了确保原始 df 保持不变,让我们应用一个虚拟函数:

>>> def foo(row: pd.Series):
... row['b'] = '42'

>>> df = pd.DataFrame([('a0','b0'),('a1','b1')], columns=['a', 'b'])
>>> df.apply(foo, axis=1)
>>> df
a b
0 a0 b0
1 a1 b1

这符合预期。但是,如果我们修改初始化此 df 的方式,foo 将应用更改:

>>> df2 = pd.DataFrame(columns=['a', 'b'])
>>> df2['a'] = ['a0','a1']
>>> df2['b'] = ['b0','b1']
>>> df2.apply(foo, axis=1)
>>> df2
a b
0 a0 42
1 a1 42

我还注意到,如果列数据类型不是“对象”类型,则上述情况不成立。为什么 apply() 在这两种情况下表现不同?

python :3.6.5

Pandas :0.23.1

最佳答案

有趣的问题!我相信您看到的行为是您使用 apply 方式的产物。

正如您正确指出的那样,apply 并非旨在用于修改数据框。但是,由于 apply 采用任意函数,因此不能保证应用该函数是幂等的并且不会更改数据帧。在这里,您找到了该行为的一个很好的例子,因为您的函数 foo 试图修改由 apply 传递给它的行。

使用 apply 修改行可能会导致这些副作用。这不是最佳做法。

相反,请考虑使用这种惯用的apply 方法。 apply 函数通常用于创建新列。以下是通常如何使用 apply 的示例,我相信它会引导您远离这个潜在的麻烦区域:

import pandas as pd
# construct df2 just like you did
df2 = pd.DataFrame(columns=['a', 'b'])
df2['a'] = ['a0','b0']
df2['b'] = ['a1','b1']

df2['b_copy'] = df2.apply(lambda row: row['b'], axis=1) # apply to each row
df2['b_replace'] = df2.apply(lambda row: '42', axis=1)
df2['b_reverse'] = df2['b'].apply(lambda val: val[::-1]) # apply to each value in b column

print(df2)

# output:
# a b b_copy b_replace b_reverse
# 0 a0 a1 a1 42 1a
# 1 b0 b1 b1 42 1b

请注意,pandas 将一行或一个单元格传递给您作为 apply 的第一个参数的函数,然后将函数的输出存储在您选择的列中。

如果您想逐行修改数据帧,请查看iterrowsloc 以获得最惯用的方法。

关于python - pandas df.apply 意外更改数据框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52457989/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com