Python 熊猫:根据索引标签与列标签条件聚合行

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

我有一个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.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