使用apply时如何将数据框的所有列传递给函数?
How to pass all columns of a dataframe to a function when using apply?
我有一个包含多个列的 pandas 数据框,例如
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(0,100,size=(100, 7)), columns=list('ABCDEFG'))
我想 apply
一个可以接受数据框所有列作为参数的函数:
# function would do something more complex potentially :)
def foo(a,b,c,d,e,f,g):
# do stuff with a,b,c,d,e,f,g. Here I do something silly/simple
return a + b*2 + c*3 + d*4 + e*5 + f*5 + g*5
现在,我想将 foo
应用于 df
的所有行。这样做的正确语法是什么?
我的尝试成功了
df.apply(lambda row: foo(row[0], row[1], row[2], row[3], row[4], row[5], row[6]), axis = 1) # terrible
df.apply(lambda row: foo(*row), axis = 1) # better
但是有没有办法更简洁地做到这一点,例如没有 lambda
?
对功能进行简单调整即可解决问题
def foo(a=df['A'],b=df['B'],c=df['C'],d=df['D'],e=df['E'],f=df['F'],g=df['G']):
return a + b*2 + c*3 + d*4 + e*5 + f*5 + g*5
df.apply(foo)
A B C D E F G
0 755 731 736 745 717 696 697
1 1365 1330 1321 1323 1332 1348 1367
2 985 1002 971 982 1012 1017 1052
3 1078 1016 1094 1034 1034 1049 1102
4 1045 1059 1041 1101 1100 1025 1041
.. ... ... ... ... ... ... ...
95 1318 1338 1341 1349 1357 1356 1358
96 1323 1387 1349 1321 1315 1370 1389
97 1066 1101 1057 1098 1132 1078 1067
98 1261 1229 1273 1312 1283 1296 1231
99 1585 1522 1537 1590 1591 1558 1548
[100 rows x 7 columns]
更新
df.apply(lambda x: x['A'] + x['B']*2 + x['C']*3 + x['D']*4 + x['E']*5 + x['F']*5 + x['G']*5,1)
0 755
1 1365
2 985
3 1078
4 1045
...
95 1318
96 1323
97 1066
98 1261
99 1585
Length: 100, dtype: int64
这是一种将数据帧的所有列传递给函数 而不使用应用或 lambda 的方法。
foo(*df.to_numpy().T)
那 return 是一个 numpy 数组。如果你需要它 return 一个 pandas 与输入具有相同索引的系列,你可以这样做:
pd.Series(foo(*df.to_numpy().T), index=df.index)
事实证明它比 lambda 方法快得多(至少对我来说 运行 python 3.5)。
>>> import timeit
>>> timeit.timeit("df.apply(lambda row: foo(*row), axis = 1)", setup="from __main__ import foo, df", number=10)
0.028233799999981102
>>> timeit.timeit("pd.Series(foo(*df.to_numpy().T), index=df.index)", setup="from __main__ import foo, df, pd", number=10)
0.0019406999999773689
>>> timeit.timeit("foo(*df.to_numpy().T)", setup="from __main__ import foo, df", number=10)
0.0004090000000189775
当 return 使用 numpy 数组时速度提高 69 倍,当 return 使用 pandas 系列并保持索引时速度提高 15 倍!
我有一个包含多个列的 pandas 数据框,例如
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(0,100,size=(100, 7)), columns=list('ABCDEFG'))
我想 apply
一个可以接受数据框所有列作为参数的函数:
# function would do something more complex potentially :)
def foo(a,b,c,d,e,f,g):
# do stuff with a,b,c,d,e,f,g. Here I do something silly/simple
return a + b*2 + c*3 + d*4 + e*5 + f*5 + g*5
现在,我想将 foo
应用于 df
的所有行。这样做的正确语法是什么?
我的尝试成功了
df.apply(lambda row: foo(row[0], row[1], row[2], row[3], row[4], row[5], row[6]), axis = 1) # terrible
df.apply(lambda row: foo(*row), axis = 1) # better
但是有没有办法更简洁地做到这一点,例如没有 lambda
?
对功能进行简单调整即可解决问题
def foo(a=df['A'],b=df['B'],c=df['C'],d=df['D'],e=df['E'],f=df['F'],g=df['G']):
return a + b*2 + c*3 + d*4 + e*5 + f*5 + g*5
df.apply(foo)
A B C D E F G
0 755 731 736 745 717 696 697
1 1365 1330 1321 1323 1332 1348 1367
2 985 1002 971 982 1012 1017 1052
3 1078 1016 1094 1034 1034 1049 1102
4 1045 1059 1041 1101 1100 1025 1041
.. ... ... ... ... ... ... ...
95 1318 1338 1341 1349 1357 1356 1358
96 1323 1387 1349 1321 1315 1370 1389
97 1066 1101 1057 1098 1132 1078 1067
98 1261 1229 1273 1312 1283 1296 1231
99 1585 1522 1537 1590 1591 1558 1548
[100 rows x 7 columns]
更新
df.apply(lambda x: x['A'] + x['B']*2 + x['C']*3 + x['D']*4 + x['E']*5 + x['F']*5 + x['G']*5,1)
0 755
1 1365
2 985
3 1078
4 1045
...
95 1318
96 1323
97 1066
98 1261
99 1585
Length: 100, dtype: int64
这是一种将数据帧的所有列传递给函数 而不使用应用或 lambda 的方法。
foo(*df.to_numpy().T)
那 return 是一个 numpy 数组。如果你需要它 return 一个 pandas 与输入具有相同索引的系列,你可以这样做:
pd.Series(foo(*df.to_numpy().T), index=df.index)
事实证明它比 lambda 方法快得多(至少对我来说 运行 python 3.5)。
>>> import timeit
>>> timeit.timeit("df.apply(lambda row: foo(*row), axis = 1)", setup="from __main__ import foo, df", number=10)
0.028233799999981102
>>> timeit.timeit("pd.Series(foo(*df.to_numpy().T), index=df.index)", setup="from __main__ import foo, df, pd", number=10)
0.0019406999999773689
>>> timeit.timeit("foo(*df.to_numpy().T)", setup="from __main__ import foo, df", number=10)
0.0004090000000189775
当 return 使用 numpy 数组时速度提高 69 倍,当 return 使用 pandas 系列并保持索引时速度提高 15 倍!