为什么pandas Series of DataFrame意味着失败,但sum不会,以及如何使它工作

时间:2014-12-30 16:59:29

标签: python pandas

在Python Pandas中可能有一种更聪明的方法可以做到这一点,但以下示例应该但不起作用:

import pandas as pd
import numpy as np

df1 = pd.DataFrame([[1, 0], [1, 2], [2, 0]], columns=['a', 'b'])
df2 = df1.copy()
df3 = df1.copy()

idx = pd.date_range("2010-01-01", freq='H', periods=3)
s = pd.Series([df1, df2, df3], index=idx)
# This causes an error
s.mean()

我不会发布整个回溯,但主要的错误信息很有趣:

TypeError: Could not convert    melt  T_s
0     6   12
1     0    6
2     6   10 to numeric

看起来数据框已经成功求和,但没有除以系列的长度。

但是,我们可以获取系列中数据帧的总和:

s.sum()

返回

      a     b
0     6   12
1     0    6
2     6   10

为什么在总和时并不意味着工作?这是一个错误还是一个缺失的功能?这确实有效:

(df1 + df2 + df3)/3.0

这样做:

s.sum()/3.0
      a  b
0     2  4.000000
1     0  2.000000
2     2  3.333333

但这当然不理想。

2 个答案:

答案 0 :(得分:8)

你可以(正如@unutbu所建议的)使用分层索引但是当你有一个三维数组时,你应该考虑使用" pandas Panel"。特别是当其中一个尺寸代表这种情况下的时间时。

小组经常被忽视,但它毕竟是熊猫这个名字的来源。 (面板数据系统或类似的东西)。

数据与原始数据略有不同,因此没有两个尺寸具有相同的长度:

df1 = pd.DataFrame([[1, 0], [1, 2], [2, 0], [2, 3]], columns=['a', 'b'])
df2 = df1 + 1
df3 = df1 + 10

可以通过几种不同的方式创建面板,但其中一种来自dict。您可以使用以下命令从索引和数据框创建dict:

s = pd.Panel(dict(zip(idx,[df1,df2,df3])))

您正在寻找的平均值只是在正确的轴上操作(在这种情况下,轴= 0):

s.mean(axis=0)

Out[80]:
          a         b
0  4.666667  3.666667
1  4.666667  5.666667
2  5.666667  3.666667
3  5.666667  6.666667

根据您的数据,sum(axis=0)会返回预期结果。

编辑:对于面板来说太晚了,因为层次索引方法已经被接受"。我要说的是,如果知道数据是" 参差不齐"在每个分组中具有未知但不同的数字。对于" square "数据,该面板绝对是走的路,并且通过更多的内置操作将显着加快。 Pandas 0.15在多级索引方面有很多改进,但在现实世界的应用程序中仍有局限性和黑暗边缘情况。

答案 1 :(得分:5)

使用

定义s
s = pd.Series([df1, df2, df3], index=idx)

您将DataFrames系列作为项目:

In [77]: s
Out[77]: 
2010-01-01 00:00:00       a  b
0  1  0
1  1  2
2  2  0
2010-01-01 01:00:00       a  b
0  1  0
1  1  2
2  2  0
2010-01-01 02:00:00       a  b
0  1  0
1  1  2
2  2  0
Freq: H, dtype: object

项目的总和是DataFrame:

In [78]: s.sum()
Out[78]: 
   a  b
0  3  0
1  3  6
2  6  0

但是当你采取平均值时,nanops.nanmean is called

def nanmean(values, axis=None, skipna=True):
    values, mask, dtype, dtype_max = _get_values(values, skipna, 0)
    the_sum = _ensure_numeric(values.sum(axis, dtype=dtype_max))
    ...

请注意,_ensure_numericsource code)会在结果总和上调用。 由于DataFrame不是数字,因此会引发错误。

这是一种解决方法。而不是使用DataFrames作为项目, 您可以使用hierarchical index

将DataFrame连接到新的DataFrame中
In [79]: s = pd.concat([df1, df2, df3], keys=idx)

In [80]: s
Out[80]: 
                       a  b
2010-01-01 00:00:00 0  1  0
                    1  1  2
                    2  2  0
2010-01-01 01:00:00 0  1  0
                    1  1  2
                    2  2  0
2010-01-01 02:00:00 0  1  0
                    1  1  2
                    2  2  0

现在您可以使用summean

In [82]: s.sum(level=1)
Out[82]: 
   a  b
0  3  0
1  3  6
2  6  0

In [84]: s.mean(level=1)
Out[84]: 
   a  b
0  1  0
1  1  2
2  2  0