Отправной точкой моего объяснения является наличие (и сравнение поведения) двух фреймов данных:
d
- оригинала фрейма данных, d2 = d.astype({'b': 'category'})
- родной элемент DataFrame, столбец b изменен на Категориальный .
Создатьгруппировка этих обоих DataFrames:
gr = d.groupby('a')
gr2 = d2.groupby('a')
Пока они выглядят одинаково, например, если вы запустите:
for key, grp in gr:
print(f'\nGroup: {key}\n{grp}')
и тот же код для gr2 , вы будетеполучите точно тот же результат.
Но результаты станут другими, когда вы попытаетесь агрегировать b столбец.
Когда вы запустите gr.b.agg('first')
(на исходном DataFrame), вы получите:
a
1 1
2 2
Name: b, dtype: int64
Результат - Series и, как ожидается, от d
content:
- для группы строк с a == 1 первое значение b равно 1 ,
- для группы строкс a == 2 первым значением b is 2 .
Но если вы запустите gr2.b.agg('first')
(на дочернем фрейме данных), вы получите:
[1, 2]
Categories (2, int64): [1, 2]
Результат будет pandas.core.arrays.categorical.Categorical тип и, что более важно, не имеет отношения с ключами группировки.
Вместо этого что-то действует как группирующими клавишами являются последовательных чисел (начальная форма 0 ).
Вы можете подтвердить это, выполнив gr2.agg({'b':'first'})
и получите:
b
0 1
1 2
Просто это источник вашей проблемы. При запуске:
gr2.agg({'b':'first', 'c':['mean', 'max']})
объединение агрегации и категориальных и "нормальных" столбцов, тогда:
- выше искусственный ключ группировки, полученный в результате агрегирования b ,
- , объединяется с фактическим ключом группировки из агрегации c .
Для (искусственного) ключа группировки 0 :
- значение для b / first равно 1 (см. выше),
- для с / среднее и с / макс значения отсутствуют, поэтому результат содержит 2 NaN с.
Для группового ключа 1 :
- для искусственный ключ, значение для b / first is 2 ,
- для true key, значения для c / mean и c / max are 1,5 и 2.0 ,
- , но Панды помещает их всех в в одном ряду.
Дляключ группировки 2 :
- нет «искусственного» ключа группировки с этим значением, поэтому в столбце b / first есть NaN ,
- для c / среднее и c / max там являются соответствующими значениями, поэтому они печатаются там.
Вывод: В таком случае не рекомендуется преобразовывать какой-либо столбец в Категориальный тип.
Использовать только оригинал DataFrame с «оригинальными» (не категориальными) типами, и вы получите ожидаемый результат.
Отредактируйте следующий комментарий по состоянию на 09: 14: 38Z
Существует противоречие междуто, что вы написали в своем посте и в упомянутом комментарии.
Ваше сообщение содержит запись:
I get the following output:
b c
first mean max
0 1 NaN NaN
1 2 1.5 2.0
2 NaN 3.5 4.0
поэтому распечатка содержит содержит NaN значения.
Но в комментарии, который вы написали Я не получаю NaN .
Чтобы проверить это противоречие, я снова сделал тест:
d = pd.DataFrame({'a': [1, 1, 2, 2], 'b': [1, 1, 2, 2], 'c': [1, 2, 3, 4]})
d2 = d.astype({'b': 'category'})
d2.groupby('a').agg({'b':'first', 'c':['mean', 'max']})
и получил:
b c
first mean max
0 1 NaN NaN
1 2 1.5 2.0
2 NaN 3.5 4.0
так же, как в вашем посте с NaN значениями.