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 шт):
Что-то я всё-равно до конца не понял. Если один столбец хотите получить, то делаете тоже самое, только для трёх столбцов группировка:
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),
})