Pandas无法在Transposed DataFrame上使用Apply

时间:2016-01-14 18:42:55

标签: python pandas

我有一个简单的功能:

def f(returns):
    base = (1 + returns.sum()) / (1 + returns).prod()
    base = pd.Series([base] * len(returns))
    exp = returns.abs() / returns.abs().sum()

return (1 + returns) * base.pow(exp) - 1.0

和一个DataFrame:

df = pd.DataFrame([[.1,.2,.3],[.4,.5,.6],[.7,.8,.9]], columns=['A', 'B', 'C'])

我可以这样做:

df.apply(f)

          A         B         C
0  0.084169  0.159224  0.227440
1  0.321130  0.375803  0.426375
2  0.535960  0.567532  0.599279

然而,换位:

df.transpose().apply(f)

会产生意外结果:

    0   1   2
0 NaN NaN NaN
1 NaN NaN NaN
2 NaN NaN NaN
A NaN NaN NaN
B NaN NaN NaN
C NaN NaN NaN

现在,我可以手动转置DataFrame:

df2 = pd.DataFrame([[1., 4., 7.],[2., 5., 8.], [3., 6., 9.]], columns=['A', 'B', 'C'])
df2.apply(f)

          A         B         C
0  0.628713  1.516577  2.002160
1  0.989529  1.543616  1.936151
2  1.160247  1.499530  1.836141

我不明白为什么我不能简单地转置然后将函数应用于DataFrame的每一行。事实上,我不知道为什么我也不能这样做:

df.apply(f, axis=1)

    0   1   2   A   B   C
0 NaN NaN NaN NaN NaN NaN
1 NaN NaN NaN NaN NaN NaN
2 NaN NaN NaN NaN NaN NaN

1 个答案:

答案 0 :(得分:2)

正如EdChum所说,问题是pandas试图将您在f内创建的Series的索引与DataFrame的索引对齐。这恰巧适用于您的第一个示例,因为您未在Series调用中指定索引,因此它使用默认的0, 1, 2,它恰好与您的原始DF相同。如果您的原始DF有其他索引,它将立即失败:

>>> df = pd.DataFrame([[.1,.2,.3],[.4,.5,.6],[.7,.8,.9]], columns=['A', 'B', 'C'], index=[8, 9, 10])
>>> df.apply(f)
     A   B   C
0  NaN NaN NaN
1  NaN NaN NaN
2  NaN NaN NaN
8  NaN NaN NaN
9  NaN NaN NaN
10 NaN NaN NaN

要修复它,请使用与DF相同的索引显式创建新系列。将d内的行更改为:

base = pd.Series([base] * len(returns), index=returns.index)

然后:

>>> df.apply(f)
           A         B         C
8   0.084169  0.159224  0.227440
9   0.321130  0.375803  0.426375
10  0.535960  0.567532  0.599279
>>> df.T.apply(f)
          8         9         10
A  0.087243  0.293863  0.453757
B  0.172327  0.359225  0.505245
C  0.255292  0.421544  0.553746