Как рассчитать пропорции вложенных групп, используя python pandas без потери исходного количества строк - PullRequest
1 голос
/ 18 февраля 2020

Учитывая следующие данные:

df = pd.DataFrame({
    'where': ['a','a','a','a','a','a'] +  ['b','b','b','b','b','b'],
    'what': ['x','y','z','x','y','z'] +  ['x','y','z','x','y','z'],
    'val' : [1,3,2,5,4,3] + [5,6,3,4,5,3]
})

Что выглядит как:

   where what  val
0      a    x    1
1      a    y    3
2      a    z    2
3      a    x    5
4      a    y    4
5      a    z    3
6      b    x    5
7      b    y    6
8      b    z    3
9      b    x    4
10     b    y    5
11     b    z    3

Я хотел бы вычислить долю what в where и создать новый столбец, который представляет это.

Столбец будет иметь дубликаты. Если я рассмотрим what = x в приведенном выше и добавим этот столбец, то данные будут выглядеть следующим образом

   where what  val   what_where_prop
0      a    x    1         6/18
1      a    y    3
2      a    z    2
3      a    x    5         6/18
4      a    y    4
5      a    z    3
6      b    x    5         9/26
7      b    y    6
8      b    z    3
9      b    x    4         9/26
10     b    y    5
11     b    z    3

Здесь 6/18 вычисляется путем нахождения общей суммы x (6 = 1 + 5) в a над общей суммой val в a. Тот же процесс используется для 9/26

Полное решение будет заполнено аналогично для y и z в последнем столбце.

1 Ответ

2 голосов
/ 18 февраля 2020

IIU C,

df['what_where_group'] = (df.groupby(['where', 'what'], as_index=False)['val']
                            .transform('sum')
                            .div(df.groupby('where')['val']
                                   .transform('sum'), 
                                 axis=0))

df

Выход:

   where what  val  what_where_prop  what_where_group
0      a    x    1                6          0.333333
1      a    y    3                7          0.388889
2      a    z    2                5          0.277778
3      a    x    5                6          0.333333
4      a    y    4                7          0.388889
5      a    z    3                5          0.277778
6      b    x    5                9          0.346154
7      b    y    6               11          0.423077
8      b    z    3                6          0.230769
9      b    x    4                9          0.346154
10     b    y    5               11          0.423077
11     b    z    3                6          0.230769

Подробности:

Первый groupby два уровня, используя что и где, используя index=False, я не устанавливаю индекс как группы, а transform sum. Далее сгруппированы только там, где и transform сумма. Наконец, разделите, используя div, первую группу на второе groupby, используя направление в виде строк с axis=0.


Другим способом:

g = df.set_index(['where', 'what'])['val']
num = g.sum(level=[0,1])
denom = g.sum(level=0)
ww_group = num.div(denom, level=0).rename('what_where_group')
df.merge(ww_group, left_on=['where','what'], right_index=True)

Выходные данные :

   where what  val  what_where_prop  what_where_group
0      a    x    1                6          0.333333
3      a    x    5                6          0.333333
1      a    y    3                7          0.388889
4      a    y    4                7          0.388889
2      a    z    2                5          0.277778
5      a    z    3                5          0.277778
6      b    x    5                9          0.346154
9      b    x    4                9          0.346154
7      b    y    6               11          0.423077
10     b    y    5               11          0.423077
8      b    z    3                6          0.230769
11     b    z    3                6          0.230769

Подробности:

В основном так же, как и раньше, просто используя шаги. И объедините результаты, чтобы применить деление к каждой строке.

...