Вычислить суммарную сумму для всех столбцов отдела

#python #python-3.x #pandas #pandas-&roupby

#python #python-3.x #pandas #pandas-&roupby

Вопрос:

У меня есть этот фрейм данных

 lst = [['AA','Z',10,1,0],['BB','Y',10,1,0],
       ['AA','Z',20,2,0],['CC','X',10,2,0]]
df1 = pd.DataFrame(lst,columns = ['first_name','last_name','val','department','is_cum'])
  

выглядит следующим образом

   first_name last_name  val  department  is_cum
0         AA         Z   10           1      NO
1         BB         Y   10           1      NO
2         AA         Z   20           2      NO
3         CC         X   10           2      NO
  

Я хочу вывести что-то вроде этого

   first_name last_name  val  department  is_cum
0         AA         Z   10           1      NO
1         BB         Y   10           1      NO
2         AA         Z   10           1     YES
3         BB         Y   10           1     YES

4         AA         Z   20           2      NO
5         CC         X   10           2      NO
6         AA         Z   30         1,2     YES
7         CC         X   10           2     YES
8         BB         Y   10           1     YES
  

Все строки с is_cum NO совпадают с входным фреймом данных, в котором вновь заполненные строки являются совокупными строками с is_cum значением YES.

Строки 2 и 3 совпадают с 0 и 1, поскольку у нас есть только одна department для выполнения кумуляции. Строка 6,7,8 представляет собой совокупность department 1 и department 2. Если у нас есть одинаковые first_name и last_name в отделах 1 и 2, чем добавлять туда val или оставлять их как есть.

Я делал

 df1.&roupby(['first_name','last_name','department']).sum().&roupby(level=0).cumsum()
  

после этого я мог бы изменить is_cum col и добавить эти строки в исходный фрейм данных. Но это не требуемый результат.

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

1. @Ben. Т Да, последняя строка — это отдел 1, а не 2. Поскольку person BB доступен только в отделе 2, как указано также во входных данных.

2. Для большего объяснения мы выполняем накопительную сумму по отделу, строка 0,1 совпадает с заданными входными данными, чем мы вычисляем совокупную сумму в строке 2,3, поскольку нечего обобщать, мы оставляем все как есть. Теперь строка 4,5 относится ко второму отделу, мы суммируем строку 0,1,4,5, почему бы не строку 2,3, потому что они уже являются суммирующей строкой, поэтому строка 6,7,8 — это суммирование строки 0,1,4,5.

Ответ №1:

Вот один из способов, с помощью pivot_table которого можно выполнить итоговую сумму по столбцам. Все остальное в значительной степени получает ожидаемый результат.

 df_ = (df1.assi&n(dpt=df1['department'], 
                  department=df1['department'].astype(str))
          .pivot_table(index=['first_name','last_name'], columns='dpt', 
                       values=['val', 'department'], 
                       a&&func={'val':sum,'department':lambda x: list(x)})
          .assi&n(val=lambda x: x['val'].cumsum(axis=1).ffill(axis=1), 
                  department=lambda x: x['department'].apply(lambda x: x.dropna().cumsum(), axis=1)
                                                        .ffill(axis=1))
                 )

res= (pd.concat([df1.assi&n(is_cum='NO', dpt=df1['department']), 
                 df_.stack().reset_index()
                    .assi&n(is_cum='YES',
                            department=lambda x: x['department'].apply(','.join))])
        .sort_values(['dpt', 'is_cum']).drop('dpt',axis=1)
        .reset_index(drop=True)
     )
  

и вы получите

 print(res)
  first_name last_name   val department is_cum
0         AA         Z  10.0          1     NO
1         BB         Y  10.0          1     NO
2         AA         Z  10.0          1    YES
3         BB         Y  10.0          1    YES
4         AA         Z  20.0          2     NO
5         CC         X  10.0          2     NO
6         AA         Z  30.0        1,2    YES
7         BB         Y  10.0          1    YES
8         CC         X  10.0          2    YES
  

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

1. @AjayChinni рад, что это работает для вас, агрегация в отделе столбцов была определенно самой сложной здесь 🙂