pandas groupby multiple columns

Сделал игрушечный датасет из трёх столбцов: person, season, target. В колонке target три значения: 0, 1 и 2.

Создаётся новая колонка:

df['count'] = df.groupby(['person', 'season'])['target'].transform('size')

Т.е. находим количество записей (строк) для каждого person в каждом season при всех значениях target.

Теперь надо уточнить значения (количество строк) для каждого случая target. Т.е. подсчитать сколько для каждого person в каждом season записей где target == 1, == 2, == 0.

Делаю так:

df['target_1'] = df.groupby(['person', 'season'])['target' == 1].transform('size')

Но получается ошибка TypeError: Transform function invalid for data types.

Искал по запросу pandas groupby multiple columns, но там не то. Лямбду тут не приспособить, apply не к месту, если брать map, то придётся отказаться от transform(). Пытался с filter(), но не справился. Ещё пишут что есть вариант решения - для каждого из трёх моих случаев (target ==1,==2,==0) создаётся своя колонка, потом они сливаются (merge). Но мне кажется, что задача несложная, и должно быть такое же несложное решение.

Короче - что делать?

И отдельный вопрос - как искать по английски, если есть условие ['target' == 1]. Ну, то есть, если groupby multiply columns это понятно, а вот это дополнительное условие?


Ответы (1 шт):

Автор решения: CrazyElf

Что-то я всё-равно до конца не понял. Если один столбец хотите получить, то делаете тоже самое, только для трёх столбцов группировка:

df['count_3'] = df.groupby(['person', 'season', 'target'])['target'].transform('size')
df

Вывод:

    person  season  target  count   count_3
0        3       3       0      2         1
1        5       1       0      5         2
2        2       2       0      2         1
...

Или вот вам 3 столбца с NA:

df_new = df.groupby(['person', 'season', 'target'])['target'].count().unstack()
df_new

Вывод:

        target    0   1   2
person  season          
     1       1  2.0 NaN 1.0
             2  2.0 2.0 4.0
             4  2.0 1.0 NaN
...

P.S. Если кто будет экспериментировать, то вот искусственные данные:

import numpy as np
import pandas as pd

n = 100
df = pd.DataFrame({
    'person': np.random.randint(1, 10, size=n), 
    'season': np.random.randint(1, 5, size=n),
    'target': np.random.randint(0, 3, size=n),
})
→ Ссылка