在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
但这当然不理想。
答案 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_numeric
(source 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
现在您可以使用sum
和mean
:
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