Python Pandas-使用numpy数组对多索引数据帧执行mean()

Python Pandas-使用numpy数组对多索引数据帧执行mean(),python,arrays,pandas,numpy,dataframe,Python,Arrays,Pandas,Numpy,Dataframe,给定一个包含Numpy数组的多索引数据帧,我想知道如何获取给定索引级别的每列的平均值 >>pd.\u版本__ '1.0.5' >>>a=np.数组(范围(20)).重塑(-1,2) >>>d=pd.concat([pd.DataFrame({(i%len(a)//2,i%2):{'a':np.array(v),'b':np.array([4,4])}).T表示枚举(a)中的i,v) >>>d a b 0 0 [0, 1] [4, 4] 1 [2, 3] [4, 4] 1 0

给定一个包含Numpy数组的多索引数据帧,我想知道如何获取给定索引级别的每列的平均值

>>pd.\u版本__
'1.0.5'
>>>a=np.数组(范围(20)).重塑(-1,2)
>>>d=pd.concat([pd.DataFrame({(i%len(a)//2,i%2):{'a':np.array(v),'b':np.array([4,4])}).T表示枚举(a)中的i,v)
>>>d
a b
0 0    [0, 1]  [4, 4]
1    [2, 3]  [4, 4]
1 0    [4, 5]  [4, 4]
1    [6, 7]  [4, 4]
2 0    [8, 9]  [4, 4]
1  [10, 11]  [4, 4]
3 0  [12, 13]  [4, 4]
1  [14, 15]  [4, 4]
4 0  [16, 17]  [4, 4]
1  [18, 19]  [4, 4]
>>>d['a'].平均数()
数组([9,10.]))
>>>d['b'].平均值()
数组([4,4.]))
到目前为止还不错

问题 当我想对所有列或给定级别的索引执行
.mean()
时,就会出现问题

获取数据帧的平均值而不是
d[]
序列,我们只获取numpy数组中第一个元素的平均值

>d.平均值()
a 9.0
b 4.0
名称:0,数据类型:float64
我们在尝试特定的索引级别时会出错

>>> d.mean(level=0)
Traceback (most recent call last):
[ ... ]
pandas.core.base.DataError: No numeric types to aggregate
>>> d['a'].mean(level=1)
Traceback (most recent call last):
[ ... ]
pandas.core.base.DataError: No numeric types to aggregate
预期产量
>d.平均值()
a[9,10]
b[4,4]
>>>d.平均值(水平=0)
a b
0    [1, 2]  [4, 4]
1    [5, 6]  [4, 4]
2   [9, 10]  [4, 4]
3  [13, 14]  [4, 4]
4  [17, 18]  [4, 4]
>>>d['a']平均值(1级)
0    [8, 9]
1  [10, 11]

我知道Pandas不会假装很好地处理Numpy阵列,但在我看来这是一个Pandas bug,但我想知道如何解决它?

使用Pandas可能有更简单的方法来实现它。但我发现了这一点:

pd.DataFrame([d.iloc[:,i].mean() for i in range(2)], columns = ["a","b"])

    a   b
0   9.0 10.0
1   4.0 4.0

pd.DataFrame([[d.iloc[range(2*i,2*i+2),j].mean() for i in range(5)] for j in range(2)], index = ["a","b"]).T

    a               b
0   [1.0, 2.0]      [4.0, 4.0]
1   [5.0, 6.0]      [4.0, 4.0]
2   [9.0, 10.0]     [4.0, 4.0]
3   [13.0, 14.0]    [4.0, 4.0]
4   [17.0, 18.0]    [4.0, 4.0]

pd.DataFrame([d.iloc[range(0,10,2),0].mean(), d.iloc[range(1,10,2),0].mean()], columns = ["a","b"])

    a    b
0   8.0  9.0
1   10.0 11.0

我又摸了摸脑袋,决定把这部作品分成几个表现良好的系列

def my_平均值(df,level=None):
如果级别不是无:
返回pd.DataFrame({
上校:{
id:series.mean()表示id,df[col]中的系列。groupby(级别=级别)
}对于df.columns.values中的列
})
其他:
返回pd.DataFrame({col:df[col].mean(),用于df.columns.values}中的col)
哪个输出足够接近我需要的

>>> my_mean(d)
     0     1
a  9.0  10.0
b  4.0   4.0
>>> my_mean(d, 0)
              a           b
0    [1.0, 2.0]  [4.0, 4.0]
1    [5.0, 6.0]  [4.0, 4.0]
2   [9.0, 10.0]  [4.0, 4.0]
3  [13.0, 14.0]  [4.0, 4.0]
4  [17.0, 18.0]  [4.0, 4.0]
>>> my_mean(d, 1)
              a           b
0    [8.0, 9.0]  [4.0, 4.0]
1  [10.0, 11.0]  [4.0, 4.0]

以下是生成预期输出的替代方法:

获取多索引级别值:

level_vals_0 = set(d.index.get_level_values(0))
level_vals_1 = set(d.index.get_level_values(1))
生成输出1:

output = {
    'a': [d.loc[(level_vals_0, level_vals_1), 'a'].mean()],
    'b': [d.loc[(level_vals_0, level_vals_1), 'b'].mean()]
}

pd.DataFrame(output).T
产出1:

a   [9.0, 10.0]
b   [4.0, 4.0]
生成输出2:

output = {
    'a': [d.loc[i, 'a'].mean() for i in level_vals_0],
    'b': [d.loc[i, 'b'].mean() for i in level_vals_0]
}

pd.DataFrame(output)
输出:

a   b
0   [1.0, 2.0]  [4.0, 4.0]
1   [5.0, 6.0]  [4.0, 4.0]
2   [9.0, 10.0] [4.0, 4.0]
3   [13.0, 14.0]    [4.0, 4.0]
4   [17.0, 18.0]    [4.0, 4.0]
a   b
0   [8.0, 9.0]  [4.0, 4.0]
1   [10.0, 11.0]    [4.0, 4.0]
生成输出3:

output = {
    'a': [d.loc[(level_vals_0, i), 'a'].mean() for i in level_vals_1],
    'b': [d.loc[(level_vals_0, i), 'b'].mean() for i in level_vals_1]
}

pd.DataFrame(output)
输出:

a   b
0   [1.0, 2.0]  [4.0, 4.0]
1   [5.0, 6.0]  [4.0, 4.0]
2   [9.0, 10.0] [4.0, 4.0]
3   [13.0, 14.0]    [4.0, 4.0]
4   [17.0, 18.0]    [4.0, 4.0]
a   b
0   [8.0, 9.0]  [4.0, 4.0]
1   [10.0, 11.0]    [4.0, 4.0]

谢谢但是,您的答复假设数据帧中的行数。也许我应该提到,我正在寻找一个大小不可知的解决方案。我的实际索引要脏得多,我不能简单地用
范围(一些数字)重新生成索引
我会根据您的数据大小,尝试计算每个案例的
一些_数
,一旦您有了它,尝试应用这种方法是的,我想我可以迭代
d.index
,但我认为这将是一个巨大的性能损失。我认为这是整洁的。请注意,您为
my_mean(d)
生成的输出与您问题中的预期输出略有不同。