Python 熊猫:根据索引标签与列标签条件聚合行
我有一个400328数据帧,其结构如下:Python 熊猫:根据索引标签与列标签条件聚合行,python,pandas,Python,Pandas,我有一个400328数据帧,其结构如下: row_idx = pd.MultiIndex.from_product([['EU', 'ROW'], ['p01.a', 'p01.b', 'p02.1.a', 'p02.1.b', 'p02.1.c', 'p03']], names=['Region', 'Prod_code']) col_idx = pd.MultiIndex.fr
row_idx = pd.MultiIndex.from_product([['EU', 'ROW'],
['p01.a', 'p01.b', 'p02.1.a', 'p02.1.b', 'p02.1.c', 'p03']],
names=['Region', 'Prod_code'])
col_idx = pd.MultiIndex.from_product([['EU', 'ROW'],
['i01.a', 'i01.b', 'i02.1.a', 'i03']],
names=['Region', 'Ind_code'])
df_in = pd.DataFrame(np.random.randint(1,10,(12,8)), index=row_idx, columns=col_idx)
print(df)
Region EU ROW
Ind_code i01.a i01.b i02.1.a i03 i01.a i01.b i02.1.a i03
Region Prod_code
EU p01.a 1 9 7 4 2 1 6 7
p01.b 1 5 1 7 2 4 2 2
p02.1.a 1 1 2 8 8 4 4 7
p02.1.b 7 7 7 5 6 7 1 3
p02.1.c 4 2 4 4 6 4 3 8
p03 7 2 9 8 8 8 4 3
ROW p01.a 4 4 5 5 5 1 6 2
p01.b 5 2 3 4 9 4 9 6
p02.1.a 4 4 8 8 4 7 6 6
p02.1.b 7 9 3 2 1 5 4 1
p02.1.c 4 2 1 2 9 8 8 5
p03 6 7 6 6 6 9 7 5
我需要通过对所有行求和来获得对称数据帧328328,对于这些行,相应的Prod_代码与Ind_代码没有对应关系,忽略首字母I和p。额外的行(在本例中为“..”、“p02.1.b”和“..”、“p02.1.c”)应与对应的父代码一起汇总到第一行,在本例中为“..”、“p02.1.a”,如下所示
#Desired output
print(df_out)
Region EU ROW
Ind_code i01.a i01.b i02.1.a i03 i01.a i01.b i02.1.a i03
Region Prod_code
EU p01.a 1 9 7 4 2 1 6 7
p01.b 1 5 1 7 2 4 2 2
p02.1.a 12 11 13 17 20 15 8 18
p03 7 2 9 8 8 8 4 3
ROW p01.a 4 4 5 5 5 1 6 2
p01.b 5 2 3 4 9 4 9 6
p02.1.a 15 15 12 12 14 20 18 12
p03 6 7 6 6 6 9 7 5
如何以优雅的Pythonic方式实现这一点?您可以尝试将第一个索引级别0和索引级别1与4位字符串片段分组,并应用数据帧值的总和 df 输出:
由于另一个答案不保留多索引,要保留并计算使用:
print(df_in)
Region EU ROW
Ind_code i01.a i01.b i02.1.a i03 i01.a i01.b i02.1.a i03
Region Prod_code
EU p01.a 5 9 6 3 4 7 7 3
p01.b 9 6 4 6 9 2 6 4
p02.1 7 1 4 6 4 2 7 4
p02.1 7 3 3 8 1 6 6 8
p02.1 2 4 7 8 9 5 5 3
p03 7 7 6 3 5 7 8 1
ROW p01.a 3 3 3 7 5 7 4 4
p01.b 8 8 1 4 4 3 3 3
p02.1 8 5 3 6 6 4 4 3
p02.1 8 1 3 5 5 5 6 5
p02.1 1 7 1 4 9 3 6 3
p03 3 6 1 5 1 8 4 1
输出:
说明:
我能知道这行df.index.get_level_values1.str.slicestop=5是什么吗?是的@Sai Kumar,它将采用多级索引的二级索引region Ind…Prod_代码并将索引切片为5个值字符串。@NagaKiran这不会根据OP的输出保留多索引。我刚刚编辑过,现在它将提供OP的输出@Sandepkadapa,感谢您的建议:-
Region EU ROW
Ind_code i01.a i01.b i02.1.a i03 i01.a i01.b i02.1.a i03
Region Prod_code
EU p01.a 6 6 7 1 7 7 8 3
p01.b 8 6 6 7 7 1 2 9
p02.1.a 10 12 8 21 17 16 13 12
p03 2 2 3 8 1 6 3 7
ROW p01.a 8 4 9 7 7 9 1 6
p01.b 7 8 3 3 7 9 7 3
p02.1.a 16 16 17 17 17 16 23 19
p03 3 3 3 9 9 6 3 8
print(df_in)
Region EU ROW
Ind_code i01.a i01.b i02.1.a i03 i01.a i01.b i02.1.a i03
Region Prod_code
EU p01.a 5 9 6 3 4 7 7 3
p01.b 9 6 4 6 9 2 6 4
p02.1 7 1 4 6 4 2 7 4
p02.1 7 3 3 8 1 6 6 8
p02.1 2 4 7 8 9 5 5 3
p03 7 7 6 3 5 7 8 1
ROW p01.a 3 3 3 7 5 7 4 4
p01.b 8 8 1 4 4 3 3 3
p02.1 8 5 3 6 6 4 4 3
p02.1 8 1 3 5 5 5 6 5
p02.1 1 7 1 4 9 3 6 3
p03 3 6 1 5 1 8 4 1
#getting level 1 values of multi-index
Prod_code = df_in.index.get_level_values(1)
#Assing these values to `Prod_code` column
df_in['Prod_code'] = Prod_code
#Setting the level 1 with values that contain duplicates
df_in.index.set_levels(Prod_code.str.slice(start=0,stop=5,step=1),
level=1,verify_integrity=False,inplace=True)
#Getting the values with only one duplicated value as per OP's condition
#Using groupby on level=0,1 of multi-index
level_0 = df_in.index.get_level_values(0)
level_1 = df_in.index.get_level_values(1)
valuestoset = df_in.groupby([level_0,level_1])['Prod_code'].first()
#Finding the sum on groupby object on level=0,1 of multi-index which contains duplicates
df_out = df_in.groupby([level_0,level_1]).sum()
#Finally setting the valuestoset to multi-index to preseve the order
df_out.index.set_levels(valuestoset,level=1,verify_integrity=False,inplace=True)
print(df_out)
Region EU ROW
Ind_code i01.a i01.b i02.1.a i03 i01.a i01.b i02.1.a i03
Region Prod_code
EU p01.a 5 9 6 3 4 7 7 3
p01.b 9 6 4 6 9 2 6 4
p02.1.a 16 8 14 22 14 13 18 15
p03 7 7 6 3 5 7 8 1
ROW p01.a 3 3 3 7 5 7 4 4
p01.b 8 8 1 4 4 3 3 3
p02.1.a 17 13 7 15 20 12 16 11
p03 3 6 1 5 1 8 4 1
print(df_in.index.get_level_values(1))
Index(['p01.a', 'p01.b', 'p02.1.a', 'p02.1.b', 'p02.1.c', 'p03', 'p01.a',
'p01.b', 'p02.1.a', 'p02.1.b', 'p02.1.c', 'p03'],
dtype='object', name='Prod_code')
Prod_code = df_in.index.get_level_values(1)
df_in['Prod_code'] = index_col
df_in.index.set_levels(Prod_code.str.slice(start=0,stop=5,step=1),
level=1,verify_integrity=False,inplace=True)
print(df_in)
Region EU ROW Prod_code
Ind_code i01.a i01.b i02.1.a i03 i01.a i01.b i02.1.a i03
Region Prod_code
EU p01.a 5 9 6 3 4 7 7 3 p01.a
p01.b 9 6 4 6 9 2 6 4 p01.b
p02.1 7 1 4 6 4 2 7 4 p02.1.a
p02.1 7 3 3 8 1 6 6 8 p02.1.b
p02.1 2 4 7 8 9 5 5 3 p02.1.c
p03 7 7 6 3 5 7 8 1 p03
ROW p01.a 3 3 3 7 5 7 4 4 p01.a
p01.b 8 8 1 4 4 3 3 3 p01.b
p02.1 8 5 3 6 6 4 4 3 p02.1.a
p02.1 8 1 3 5 5 5 6 5 p02.1.b
p02.1 1 7 1 4 9 3 6 3 p02.1.c
p03 3 6 1 5 1 8 4 1 p03
df_in.groupby([level_0,level_1])['Prod_code'].first()
Region Prod_code
EU p01.a p01.a
p01.b p01.b
p02.1 p02.1.a
p03 p03
ROW p01.a p01.a
p01.b p01.b
p02.1 p02.1.a
p03 p03
Name: Prod_code, dtype: object
df_in.groupby([level_0,level_1]).sum()
Region EU ROW
Ind_code i01.a i01.b i02.1.a i03 i01.a i01.b i02.1.a i03
Region Prod_code
EU p01.a 5 9 6 3 4 7 7 3
p01.b 9 6 4 6 9 2 6 4
p02.1 16 8 14 22 14 13 18 15
p03 7 7 6 3 5 7 8 1
ROW p01.a 3 3 3 7 5 7 4 4
p01.b 8 8 1 4 4 3 3 3
p02.1 17 13 7 15 20 12 16 11
p03 3 6 1 5 1 8 4 1
df_out.index.set_levels(valuestoset,level=1,verify_integrity=False,inplace=True)
Region EU ROW
Ind_code i01.a i01.b i02.1.a i03 i01.a i01.b i02.1.a i03
Region Prod_code
EU p01.a 5 9 6 3 4 7 7 3
p01.b 9 6 4 6 9 2 6 4
p02.1.a 16 8 14 22 14 13 18 15
p03 7 7 6 3 5 7 8 1
ROW p01.a 3 3 3 7 5 7 4 4
p01.b 8 8 1 4 4 3 3 3
p02.1.a 17 13 7 15 20 12 16 11
p03 3 6 1 5 1 8 4 1