Python Pandas:将函数应用于数据帧行时返回多个字段值

问题描述:

我需要将多个函数应用于数据帧行。这些函数的参数从单个行的两个或多个字段获取值。例如:Python Pandas:将函数应用于数据帧行时返回多个字段值

d = {                          
    'a': [1,1,1,1],                       
    'b': [2,2,2,2],                       
    'c': [3,3,3,3],                       
    'd': [4,4,4,4]                        
}                           

df1 = pd.DataFrame(d)                      

def f1(x,y):                         
    return x + 2*y                       

def f2(x,y):                         
    return y + 2*x                       

df2 = pd.DataFrame()                       
df2['val1'] = df1.apply(lambda r: f1(r.a, r.b),1)               
df2['val2'] = df1.apply(lambda r: f2(r.c, r.d),1)               

当依次应用每个函数时,Pandas会对所有数据帧行进行单独迭代。在这个例子中熊猫迭代数据帧两次。因此,我得到:

In [10]: df2                         
Out[10]:                          
    val1 val2                        
0  5 10                        
1  5 10                        
2  5 10                        
3  5 10                        

有没有什么办法可以在数据帧上单次传递两个或更多的函数?这样,应用程序应该为一行中的多个字段返回值。此外,这种情况包括应用一个函数返回超过一个字段的值。如何才能做到这一点?

如果你的函数是线性的或者可以用某种方式进行矢量化,我们可以做很多很酷的事情。

t = pd.DataFrame(dict(val1=[1, 2, 0, 0], val2=[0, 0, 2, 1]), df1.columns) 
df1.dot(t) 

或用

pd.DataFrame(
    df1.values.dot(
     np.array([[1, 0], [2, 0], [0, 2], [0, 1]]) 
    ), 
    df1.index, 
    ['val1', 'val2'] 
) 

enter image description here

,也可以定义更快的新功能,通过组合应用

def f3(r): 
    return pd.Series(dict(val1=f1(r.a, r.b), val2=f2(r.c, r.d))) 

df1.apply(f3, 1) 
+1

想这一次是关于我的MacBookPro6,2,英特尔酷睿i5 2 74MB csv文件, 53,处理器:1,内核:2,L2缓存(每核):256 KB,L3缓存:3 MB,内存:4 GB。在OSX EL Capitan版本下。 10.11.6。一个接一个的函数应用程序的工作会更糟糕。总共消耗了大约6GB的内存并从未完成,只好杀了。美学上这个解决方案看起来不错,对我来说最易读。我认为这种降级是由于字典和系列对象需要额外的内存分配。 – zork

+0

@ zork很高兴知道。这些是你需要的实际功能吗?如果是的话,我们可以很容易地将这个向量化。 – piRSquared

+0

不,功能不同... – zork

你可以在同一时间填补他们的功能:

def f3(x,y,z,a): 
    return x + 2*y, a + 2*z 
df3 = pd.DataFrame() 
df3['val1'], df3['val2'] = f3(df1.a, df1.b, df1.c, df1.d) 
+1

这是一个好方法,但不是每个函数都可以在dataFrame上像这样运行。 也可以像'df3 ['val1'],df3 ['val2'] = f1(df1.a,df1.b),f2(df1.c,df1.d)' –

+0

'与我的实际功能和论点。我得到这个错误:'/Users/user/usr/anaconda_2.7/anaconda/lib/python2.7/site-packages/pandas/core/generic.pyc in __getattr __(self,name) 2670 if self in self。 _info_axis: 2671返回自[名称] - > 2672返回对象.__的getAttribute __(个体,名称) 2674 DEF __setattr __(个体,名称,值): AttributeError的:“系列的对象没有属性 '分裂' ' – zork

如果您不希望创建新的功能,你可以使用下面的一行:

>>> df2 = df1.apply(lambda r: pd.Series({'val1': f1(r.a, r.b), 'val2': f2(r.c, r.d)}), axis=1) 
>>> df2 
    val1 val2 
0  5 10 
1  5 10 
2  5 10 
3  5 10