2014-05-15 253 views
15

我有一个timeindex和包含三维向量的坐标3列一数据帧:熊猫申请函数返回多个值的行中大熊猫数据帧

      x    y    z 
ts 
2014-05-15 10:38   0.120117  0.987305  0.116211 
2014-05-15 10:39   0.117188  0.984375  0.122070 
2014-05-15 10:40   0.119141  0.987305  0.119141 
2014-05-15 10:41   0.116211  0.984375  0.120117 
2014-05-15 10:42   0.119141  0.983398  0.118164 

予想变换应用到每个行也返回一个矢量

def myfunc(a, b, c): 
    do something 
    return e, f, g 

,但如果我这样做:

df.apply(myfunc, axis=1) 

我结束ü p与元素为元组的Pandas系列。这是因为应用程序将取消myfunc的结果而不解压缩它。我如何更改myfunc以便获得具有3列的新df?

编辑:

下面工作的所有解决方案。 Series解决方案允许使用列名,List解决方案似乎执行得更快。

def myfunc1(args): 
    e=args[0] + 2*args[1] 
    f=args[1]*args[2] +1 
    g=args[2] + args[0] * args[1] 
    return pd.Series([e,f,g], index=['a', 'b', 'c']) 

def myfunc2(args): 
    e=args[0] + 2*args[1] 
    f=args[1]*args[2] +1 
    g=args[2] + args[0] * args[1] 
    return [e,f,g] 

%timeit df.apply(myfunc1 ,axis=1) 

100 loops, best of 3: 4.51 ms per loop 

%timeit df.apply(myfunc2 ,axis=1) 

100 loops, best of 3: 2.75 ms per loop 

回答

4

只是返回一个列表而不是元组。

In [81]: df 
Out[81]: 
          x   y   z 
ts            
2014-05-15 10:38:00 0.120117 0.987305 0.116211 
2014-05-15 10:39:00 0.117188 0.984375 0.122070 
2014-05-15 10:40:00 0.119141 0.987305 0.119141 
2014-05-15 10:41:00 0.116211 0.984375 0.120117 
2014-05-15 10:42:00 0.119141 0.983398 0.118164 

[5 rows x 3 columns] 

In [82]: def myfunc(args): 
    ....:  e=args[0] + 2*args[1] 
    ....:  f=args[1]*args[2] +1 
    ....:  g=args[2] + args[0] * args[1] 
    ....:  return [e,f,g] 
    ....: 

In [83]: df.apply(myfunc ,axis=1) 
Out[83]: 
          x   y   z 
ts            
2014-05-15 10:38:00 2.094727 1.114736 0.234803 
2014-05-15 10:39:00 2.085938 1.120163 0.237427 
2014-05-15 10:40:00 2.093751 1.117629 0.236770 
2014-05-15 10:41:00 2.084961 1.118240 0.234512 
2014-05-15 10:42:00 2.085937 1.116202 0.235327 
+3

这不起作用。它返回一个其元素是列表的系列。我在熊猫0.18.1 –

18

返回Series它会将它们放在DataFrame中。

def myfunc(a, b, c): 
    do something 
    return pd.Series([e, f, g]) 

这有奖金,你可以给每个结果列的标签。如果你返回一个DataFrame,它只需为该组插入多行。

+0

在[灵活应用]中查看更多示例(http://pandas-docs.github.io/pandas-docs-travis/groupby.html#flexible-apply) –

+1

该系列答案似乎是规范的答案。但是,在0.18.1版本上,该系列解决方案需要比运行多次的时间长4倍。 –

2

发现了一个可能的解决方案,通过改变MYFUNC返回一个像这样的np.array:

import numpy as np 

def myfunc(a, b, c): 
    do something 
    return np.array((e, f, g)) 

任何更好的解决方案?

5

基于卓越answer通过@ U2EF1,我已经创建了一个应用指定的函数返回元组到数据帧领域,并扩展结果返回给数据帧一个方便的功能。

def apply_and_concat(dataframe, field, func, column_names): 
    return pd.concat((
     dataframe, 
     dataframe[field].apply(
      lambda cell: pd.Series(func(cell), index=column_names))), axis=1) 

用法:

df = pd.DataFrame([1, 2, 3], index=['a', 'b', 'c'], columns=['A']) 
print df 
    A 
a 1 
b 2 
c 3 

def func(x): 
    return x*x, x*x*x 

print apply_and_concat(df, 'A', func, ['x^2', 'x^3']) 

    A x^2 x^3 
a 1 1 1 
b 2 4 8 
c 3 9 27 

希望它可以帮助别人。