Python 将聚合函数应用于分层索引中多个索引的系统方法 问题
我希望有一个更系统的方法来聚合多个频率间隔的频率 以下数据帧包含表示时间频率数据的随机数据。其列索引包含以下级别:Python 将聚合函数应用于分层索引中多个索引的系统方法 问题,python,pandas,aggregate,multi-index,Python,Pandas,Aggregate,Multi Index,我希望有一个更系统的方法来聚合多个频率间隔的频率 以下数据帧包含表示时间频率数据的随机数据。其列索引包含以下级别: 条件 渠道 频率 生成数据帧的代码如下所示: 将numpy导入为np 作为pd进口熊猫 pidx=pd.indexlice D=np.零点((32,2,2,6))#时间点、条件、通道、频率 对于范围(6)中的i: D[:,0,0,i]=np.arange(i,i+32,1)#C0,ch01 D[:,0,1,i]=np.arange(i+1,i+32+1,1)#C0,ch02 D[:
将numpy导入为np
作为pd进口熊猫
pidx=pd.indexlice
D=np.零点((32,2,2,6))#时间点、条件、通道、频率
对于范围(6)中的i:
D[:,0,0,i]=np.arange(i,i+32,1)#C0,ch01
D[:,0,1,i]=np.arange(i+1,i+32+1,1)#C0,ch02
D[:,1,0,i]=np.arange(i+2,i+32+2,1)#C1,ch01
D[:,1,1,i]=np.arange(i+3,i+32+3,1)#C1,ch02
条件=['C0','C1']
通道=[“ch{:02}”。np.arange(1,3)中i的格式(i)]
频率=np.arange(1,7)
#Columns多索引
cidx=来自产品的pd.多索引([条件、频道、频率])
#重塑为二维
D=D.重塑((D.形状[0],-1))
#创建数据帧
df=pd.DataFrame(D,columns=cidx)
当前解决方案
目前我做了以下工作
fbands={
“fb1”:[pidx[1:3]],
“fb2”:[pidx[2:5]],
“fb3”:[pidx[4:6]]
}
def频带平均值(df,fb):
返回df.loc(axis=1)[:,:,fb].groupby(axis=1,level=[0,1]).mean()
dffbands=dict((k,频带_平均值(df,fbands[k]),表示fbands中的k)
df_结果=pd.concat(dffbands,轴=1)
但是,对于后一种代码,列索引级别没有得到维护,更具体地说,df_result
的第一级包含在fbands
中定义的每个频率间隔的名称。我会通过交换列级别来解决这个问题,但这似乎很麻烦
问题:
我想知道是否有一种更系统的方法,在保持列索引级别的同时,一次性将聚合函数应用于多个频率间隔。最后,columnindex的最后一级应该是
fb1
,fb2
,fb3
)我猜你是把频率分成两组。如果是,请尝试:
# it's convenient to groupby over rows than
data = df.T.reset_index()
data.rename(columns={'level_0':'condition',
'level_1': 'channel',
'level_2': 'frequency'},
inplace=True)
# groupby and compute mean
# review your frequency grouping here
# change mapping frequency -> frequency_band_group
new_df = data.groupby(['condition', 'channel', (data.frequency-1)//2]).mean()
new_df.drop('frequency', axis=1, inplace=True)
# change name for frequency index
new_df.index.rename('frequency_band', level=2, inplace=True)
# change label for frequency band
new_df.index.set_levels([conditions, channels, ['fb1','fb2','fb3']], inplace=True)
# transform back to get multi-level columns:
new_df.T
new_df=data.groupby(['condition','channel',(data.frequency-1)//2]).mean()
new_df.drop('frequency',axis=1,inplace=True)如果我没有弄错,我会这样做:
fbands={
'fb1' : [0,3],
'fb2' : [2,5],
'fb3' : [4,6]
}
for co_i in df.columns.levels[0]:
for cha_i in df.columns.levels[1]:
for k,v in fbands.items():
df[co_i,cha_i,k] = df[co_i,cha_i,].T[v[0]:v[1]].mean()
df['C0','ch01','fb1'] = df.loc(axis=1)[pd.IndexSlice['C0','ch01',['f1','f2','f3'],:]].mean(axis=1)
更新:注意这里的切片不是基于标签的,因此您实际上需要v[0]-1:v[1]
;为了更清楚地说明这一点,我建议您简化您的df
:
D=np.zeros((32,2,2,6))
for i in range(6):
D[:,0,0,i]=np.arange(i,i+32,1) # C0, ch01
D[:,0,1,i]=np.arange(i+1,i+32+1,1) # C0, ch02
D[:,1,0,i]=np.arange(i+2,i+32+2,1) # C1, ch01
D[:,1,1,i]=np.arange(i+3,i+32+3,1) # C1, ch02
使df.head(3)
返回:
C0 C1
ch01 ch02 ch01 ch02
1 2 3 4 5 6 1 2 3 4 5 6 1 2 3 4 5 6 1 2 3 4 5 6
0 0.0 1.0 2.0 3.0 4.0 5.0 1.0 2.0 3.0 4.0 5.0 6.0 2.0 3.0 4.0 5.0 6.0 7.0 3.0 4.0 5.0 6.0 7.0 8.0
1 1.0 2.0 3.0 4.0 5.0 6.0 2.0 3.0 4.0 5.0 6.0 7.0 3.0 4.0 5.0 6.0 7.0 8.0 4.0 5.0 6.0 7.0 8.0 9.0
2 2.0 3.0 4.0 5.0 6.0 7.0 3.0 4.0 5.0 6.0 7.0 8.0 4.0 5.0 6.0 7.0 8.0 9.0 5.0 6.0 7.0 8.0 9.0 10.0
这样,我们就可以真正验证我们的期望!我现在使用的是fbands
作为数组,而不是dict,因此排序变得很好(也可以使用collections
中的OrderedDict
)
返回:
C0 C1
ch01 ch02 ch01 ch02
fb1 fb2 fb3 fb1 fb2 fb3 fb1 fb2 fb3 fb1 fb2 fb3
0 1.0 2.5 4.0 2.0 3.5 5.0 3.0 4.5 6.0 4.0 5.5 7.0
1 2.0 3.5 5.0 3.0 4.5 6.0 4.0 5.5 7.0 5.0 6.5 8.0
2 3.0 4.5 6.0 4.0 5.5 7.0 5.0 6.5 8.0 6.0 7.5 9.0
现在,fb*
列实际上反映了频率fb1:[1,2,3]、fb2:[2,3,4,5]和fb3:[4,5,6]的平均值,我希望您能这样做
更新2:
请注意,如果您将频率设置为这样:
frequencies = ["f{0}".format(i) for i in np.arange(1,7)]
然后,您可以在ch01
的C0
中创建频率的平均值'f1'、'f2'、'f3'
,如下所示:
fbands={
'fb1' : [0,3],
'fb2' : [2,5],
'fb3' : [4,6]
}
for co_i in df.columns.levels[0]:
for cha_i in df.columns.levels[1]:
for k,v in fbands.items():
df[co_i,cha_i,k] = df[co_i,cha_i,].T[v[0]:v[1]].mean()
df['C0','ch01','fb1'] = df.loc(axis=1)[pd.IndexSlice['C0','ch01',['f1','f2','f3'],:]].mean(axis=1)
我不确定我是否遵循了
fbands
的逻辑。看起来pidx[1:3]
与pidx[2:5]
重叠?@QuangHoang,频率间隔重叠是可以的。频率不是按大小为2的组分组的。示例中的频率组是任意的,但应能够采用任何范围。明确规定。另外,data.groupby(['condition'、'channel'、(data.frequency-1)//2]).mean()
抛出TypeError:-:'str'和'int'不支持的操作数类型,因为它是从str类型中减去(和除以)的。您的第二次更新正是我要找的!非常感谢。