Python 使用apply时,如何将数据帧的所有列传递给函数?

Python 使用apply时,如何将数据帧的所有列传递给函数?,python,pandas,idioms,Python,Pandas,Idioms,我有一个包含多个列的熊猫数据框架,如 import pandas as pd import numpy as np df = pd.DataFrame(np.random.randint(0,100,size=(100, 7)), columns=list('ABCDEFG')) 我想对其应用一个函数,该函数可以接受数据帧的所有列作为参数: # function would do something more complex potentially :) def foo(a,b,c,d,e,

我有一个包含多个列的熊猫数据框架,如

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randint(0,100,size=(100, 7)), columns=list('ABCDEFG'))
我想对其应用一个函数,该函数可以接受数据帧的所有列作为参数:

# 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)
更新


下面是一种不使用apply或lambdas将数据帧的所有列传递给函数的方法

返回一个numpy数组。如果需要它返回索引与输入相同的熊猫系列,可以执行以下操作:

 pd.Series(foo(*df.to_numpy().T), index=df.index)
事实证明,至少对于运行python 3.5的我来说,它比lambda方法快得多

>>> 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

当返回numpy数组时,速度快69倍;当返回熊猫系列并保留索引时,速度快15倍

如果函数中的arg与col名称匹配,则可以创建一个dict,然后对代码较少的dict进行迭代。您还可以压缩这两个iterable,并将函数应用到iterable的末尾。为什么要在此处使用apply?谢谢,但是。。。在我的示例中,预期结果是一系列的len100!注意,传递轴=1以应用,结果逐行输入。我已使用更简单的版本更新。在您的情况下,需要一个循环,因为您需要单个值并希望对其执行操作。无法想象任何其他方式。注意,我也可能错。df.mulpd.Seriesdata=[1,2,3,4,5,5],索引=df.columns.sumaxis=1@ansev这个想法是要有一个有许多参数的函数,而不是简单地乘以列值,我将使这个问题更一般。。。
foo(*df.to_numpy().T)
 pd.Series(foo(*df.to_numpy().T), index=df.index)
>>> 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