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

Мат*_*нер 4 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()
Run Code Online (Sandbox Code Playgroud)

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

TypeError: Could not convert    melt  T_s
0     6   12
1     0    6
2     6   10 to numeric
Run Code Online (Sandbox Code Playgroud)

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

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

s.sum()
Run Code Online (Sandbox Code Playgroud)

返回

      a     b
0     6   12
1     0    6
2     6   10
Run Code Online (Sandbox Code Playgroud)

什么意思不是指总和时的工作?这是一个错误还是一个缺失的功能?这确实有效:

(df1 + df2 + df3)/3.0
Run Code Online (Sandbox Code Playgroud)

这样做:

s.sum()/3.0
      a  b
0     2  4.000000
1     0  2.000000
2     2  3.333333
Run Code Online (Sandbox Code Playgroud)

但这当然不理想.

Phi*_*per 8

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

小组是经常被忽视,但它毕竟是在那里的名字熊猫的由来.(面板数据系统或类似的东西).

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

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

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

s = pd.Panel(dict(zip(idx,[df1,df2,df3])))
Run Code Online (Sandbox Code Playgroud)

你正在寻找的意思只是在正确的轴上操作(在这种情况下,轴= 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
Run Code Online (Sandbox Code Playgroud)

使用您的数据,sum(axis=0)返回预期结果.

编辑: 对于面板来说太晚了,因为分层索引方法已被"接受".我要说的是,如果数据在每个分组中被称为" 参差不齐 "且数据未知但数量不同,那么这种方法更可取.对于" 方形 "数据,该面板绝对是最佳选择,并且通过更多内置操作将显着提高速度.Pandas 0.15在多级索引方面有很多改进,但在现实世界的应用程序中仍有局限性和黑暗边缘情况.


unu*_*tbu 5

当你定义s

s = pd.Series([df1, df2, df3], index=idx)
Run Code Online (Sandbox Code Playgroud)

你得到一个带有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
Run Code Online (Sandbox Code Playgroud)

项目的总和是DataFrame:

In [78]: s.sum()
Out[78]: 
   a  b
0  3  0
1  3  6
2  6  0
Run Code Online (Sandbox Code Playgroud)

但当你采取平均值时,nanops.nanmean称为:

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))
    ...
Run Code Online (Sandbox Code Playgroud)

请注意,在结果总和上调用_ensure_numeric(源代码).由于DataFrame不是数字,因此会引发错误.

这是一个解决方法.您可以将DataFrame连接到具有分层索引的新DataFrame,而不是将具有DataFrames的Series作为项目:

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
Run Code Online (Sandbox Code Playgroud)

现在你可以采取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
Run Code Online (Sandbox Code Playgroud)