Агрегировать в multiindex, устанавливая имена некоторых столбцов в качестве имен строк и суммируя наборы столбцов по ним

#python #python-3.x #pandas #dataframe

#python #python-3.x #pandas #фрейм данных

Вопрос:

Короче говоря, я хотел бы перейти от этого

 cat1  cat2  str1_count  str1_a  str1_b  str2_count  str2_a  str2_b

val1  val1         num     num     num         num     num     num
val1  val2         num     num     num         num     num     num                          
val2  val1         num     num     num         num     num     num
val1  val1         num     num     num         num     num     num
val3  val3         num     num     num         num     num     num
val2  val2         num     num     num         num     num     num
  

К этому

 cat1  cat2                  count  avg_a   avg_b  

val1  val1          str1      num    num     num      
                    str2      num    num     num                                  
      val2          str1      num    num     num           
                    str2      num    num     num           
val2  val1          str1      num    num     num           
                    str2      num    num     num           
      val2          str1      num    num     num           
                    str2      num    num     num
val3  val3          str1      num    num     num           
                    str2      num    num     num           
       
  

На данный момент я немного не в своей тарелке.

Ответ №1:

Сначала преобразуйте столбцы с no _ в MultiIndex DataFrame.set_index by MultiIndex in columns , затем разделите столбцы на DataFrame.stack , последнее изменение формы по mean и последнее агрегирование sum и MultiIndex для всех 3 уровней, которые:

 df1 = df.set_index(['cat1','cat2'])
df1.columns = df1.columns.str.split('_', expand=True)
df1 = df1.stack(0).groupby(level=[0,1,2]).agg({'count':'sum', 'a':'mean', 'b':'mean'})
  

Если необходимо изменить имена столбцов, возможно использование именованной агрегации:

 df1 = df.set_index(['cat1','cat2'])
df1.columns = df1.columns.str.split('_', expand=True)
df1 = (df1.stack(0)
          .groupby(level=[0,1,2])
          .agg(count=('count', 'sum'), avg_a=('a', 'mean'), avg_b=('b', 'mean')))
  

Комментарии:

1. Да, это не сработает, поскольку это просто даст мне список столбцов в виде строк по желаемому индексу. И я хотел бы иметь только 2 строки с [str1_a, str1_b] в качестве среднего значения в строке str1 в новых столбцах [avg_a, avg_b] и [str2_a, str2_b] в качестве среднего значения в строке str2 в тех же столбцах [avg_a, avg_b]

2. @DrDro- Я проверяю еще раз, и ответ был отредактирован, но не уверен, что это то, что нужно.