也许晚了,但我认为这可能对提出这个问题的人特别有帮助。
当我们使用foo
like时:
def foo(row: pd.Series):
row['b'] = '42'
然后将其用于:
df.apply(foo, axis=1)
我们不会期望发生任何变化,df
但它会发生。为什么?
让我们回顾一下幕后发生的事情:
apply
函数调用foo
并将一行传递给它。由于它不是types
python 中的特定类型(如 int、float、str、...),而是一个对象,因此根据 python 规则,它通过引用而不是值传递。所以它与函数发送的行完全等价apply
。(值相等,并且都指向同一个内存块。)所以对函数的任何更改row
都会foo
改变row
- 它的类型是pandas.series
什么并且指向一个内存块那df.row
驻留- 立即。
我们可以重写foo
(我命名它bar
)函数以不就地改变任何东西。(通过深度复制 row
,这意味着在 ram 的另一个单元格上创建另一行具有相同值的行)。这就是我们lambda
在apply
函数中使用时发生的事情。
def bar(row: pd.Series):
row_temp=row.copy(deep=True)
row_temp['b'] = '42'
return row_temp
完整代码
import pandas as pd
#Changes df in place -- not like lamda
def foo(row: pd.Series):
row['b'] = '42'
#Do not change df inplace -- works like lambda
def bar(row: pd.Series):
row_temp = row.copy(deep=True)
row_temp['b'] = '42'
return row_temp
df2 = pd.DataFrame(columns=['a', 'b'])
df2['a'] = ['a0', 'a1']
df2['b'] = ['b0', 'b1']
print(df2)
# No change inplace
df_b = df2.apply(bar, axis=1)
print(df2)
# bar function works
print(df_b)
print(df2)
# Changes inplace
df2.apply(foo, axis=1)
print(df2)
输出
#df2 before any change
a b
0 a0 b0
1 a1 b1
#calling df2.apply(bar, axis=1) not changed df2 inplace
a b
0 a0 b0
1 a1 b1
#df_b = df2.apply(bar, axis=1) #bar is working as expected
a b
0 a0 42
1 a1 42
#print df2 again to assure it is not changed
a b
0 a0 b0
1 a1 b1
#call df2.apply(foo, axis=1) -- as we see foo changed df2 inplace ( to compare with bar)
a b
0 a0 42
1 a1 42