Добавить сумму во все сгруппированные строки в кадре данных pandas

У меня есть кадр данных, и я хочу сгруппировать его первый и второй столбцы, а затем получить ожидаемый результат, как указано ниже:

df = pd.DataFrame({'First':list('abcababcbc'), 'Second':list('qeeeeqqqeq'),'Value_1':np.random.randint(4,50,10),'Value_2':np.random.randint(40,90,10)})
print(df)

Output>

   First    Second  Value_1     Value_2
0   a         q        17         70
1   b         e        44         47
2   c         e         5         56
3   a         e        23         58
4   b         e        10         76
5   a         q        11         67
6   b         q        21         84
7   c         q        42         67
8   b         e        36         53
9   c         q        16         63

Когда я сгруппировал этот DataFrame с помощью groupby, я получаю вывод ниже:

def func(arr,columns):
    return arr.sort_values(by = columns).drop(columns, axis = 1)

df.groupby(['First','Second']).apply(func, columns = ['First','Second'])

                Value_1      Value_2
First Second            
a       e     3     23         58
        q     0     17         70
              5     11         67
b       e     1     44         47
              4     10         76
              8     36         53
        q     6     21         84
c       e     2     5          56
        q     7     42         67
              9     16         63

Однако я хочу вывести ниже:

Expected output:

                Value_1      Value_2
First Second            
a       e     3     23         58
            All     23         58
        q     0     17         70
              5     11         67
            All     28        137   
b       e     1     44         47
              4     10         76
              8     36         53
            All     90         176
        q     6     21         84
            All     21         84
c       e     2     5          56
            All     5          56
        q     7     42         67
              9     16         63
            All     58         130

Нет необходимости печатать строку All, а нужно печатать сумму всех сгруппированных строк.


person Alpha Green    schedule 30.01.2021    source источник


Ответы (3)


Вы можете попробовать это:

  1. сбросить индекс в вашей группе:

    d1 = df.groupby(['Первый','Второй']).apply(func, columns = ['Первый','Второй']).reset_index()

  2. Затем сгруппируйте по «Первому» и «Второму» и просуммируйте столбцы значений.

    d2 = d.groupby(['Первый', 'Второй']).sum().reset_index()

  3. Создайте столбец level_2 в новом фрейме данных и соедините его с исходным, чтобы получить желаемый результат.

    d2.loc[:,'level_2'] = 'Все' pd.concat([d1,d2],0).sort_values(by = ['Первый', 'Второй'])

person Jorge    schedule 30.01.2021

Не уверен в своей функции; однако вы можете разбить его на два этапа:

Создайте индексированный фрейм данных, в котором вы добавляете столбцы First и Second к существующему индексу:

df.index = df.index.astype(str).rename("Total")
indexed = df.set_index(["First", "Second"], append=True).reorder_levels(
    ["First", "Second", "Total"]
)

indexed


                     Value_1    Value_2
First   Second  Total       
   a       q       0    17  70
   b       e       1    44  47
   c       e       2    5   56
   a       e       3    23  58
   b       e       4    10  76
   a       q       5    11  67
   b       q       6    21  84
   c       q       7    42  67
   b       e       8    36  53
   c       q       9    16  63

Создайте агрегацию, сгруппированную по First и Second:

summary = (
    df.groupby(["First", "Second"])
    .sum()
    .assign(Total="All")
    .set_index("Total", append=True)
)

summary

                        Value_1     Value_2
  First     Second  Total       
      a        e    All     23      58
      q             All     28      137
      b        e    All     90      176
      q             All     21      84
      c        e    All     5       56
      q             All     58      130

Объедините кадры данных indexed и summary:

pd.concat([indexed, summary]).sort_index(level=["First", "Second"])

                     Value_1    Value_2
First   Second  Total        
    a   e         3     23  58
                All     23  58
    q             0     17  70
                  5     11  67
                All     28  137
    b   e         1     44  47
                  4     10  76
                  8     36  53
                All     90  176
    q             6     21  84
                All     21  84
    c   e         2     5   56
                All     5   56
    q             7     42  67
                  9     16  63
                All     58  130
person sammywemmy    schedule 30.01.2021

person    schedule
comment
Спасибо за ваш ответ, это решение облегчило мне понимание. - person Alpha Green; 30.01.2021