Pandas groupby применяет странное поведение, когда NaN в столбце группы - PullRequest
4 голосов
/ 29 мая 2020

У меня неожиданные результаты Pandas groupby-apply, и я не могу понять точную причину.

Ниже у меня есть фреймы данных, которые равны, за исключением порядка двух значений. df1 дает результаты, которых я ожидал, но df2 дает совершенно другой результат. the group_col и выполните value_counts из value_col для каждой группы, включая переиндекс, чтобы включить все возможные значения в результат. Я получаю следующее для df1:

df1.groupby('group_col').value_col.apply(lambda x: x.value_counts().reindex(index=[1,2,3]))

group_col   
0.0        1    NaN
           2    3.0
           3    NaN
Name: value_col, dtype: float64

Он правильно находит 1 группу и возвращает мультииндексный ряд с value_counts для каждого возможного значения. Но когда я запускаю то же самое на df2, я получаю совершенно другой результат:

0    NaN
1    NaN
2    3.0
3    NaN
Name: value_col, dtype: float64

Здесь результат содержит индекс, соответствующий исходному DataFrame, вместо мультииндекса, который я ожидал. Я подумал, что это может иметь какое-то отношение к столбцу группы, начинающемуся с np.nan, но затем я попытался отбросить последнюю строку и снова получил ожидаемый результат, так что, очевидно, причина в другом.

df2.head(3).groupby('group_col').value_col.apply(lambda x: x.value_counts().reindex(index=[1,2,3]))

group_col   
0.0        1    NaN
           2    2.0
           3    NaN
Name: value_col, dtype: float64

Что может быть причиной этого?

1 Ответ

1 голос
/ 03 июня 2020

Давайте начнем с рассмотрения некоторых простых вычислений группировки, чтобы понять, как pandas работает с ним.

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

In [4]: df1.groupby('group_col')['value_col'] \
   ...: .apply(lambda x: {'sum': x.sum(), 'mean': x.mean()})
Out[4]: 
group_col
0.0        sum     6.0
           mean    2.0
Name: value_col, dtype: float64

In [5]: df2.groupby('group_col')['value_col'] \
   ...: .apply(lambda x: {'sum': x.sum(), 'mean': x.mean()})
Out[5]: 
group_col
0.0        sum     6.0
           mean    2.0
Name: value_col, dtype: float64

В следующем случае индекс исходного DataFrame сохраняется. Ключи группировки не содержатся в результате Series.

In [6]: df1.groupby('group_col')['value_col'].apply(lambda x: x / len(x))
Out[6]: 
0    0.666667
1         NaN
2    0.666667
3    0.666667
Name: value_col, dtype: float64

In [7]: df2.groupby('group_col')['value_col'].apply(lambda x: x / len(x))
Out[7]: 
0         NaN
1    0.666667
2    0.666667
3    0.666667
Name: value_col, dtype: float64

Что заставляет pandas вести себя по-другому, когда он создает индекс комбинированного объекта?

На самом деле это основано на , был ли индекс изменен агрегированием или нет . Если индекс исходного объекта и результирующего объекта совпадает, он решает повторно использовать исходный индекс. С другой стороны, когда индекс отличается от исходного объекта, он использует ключ группы в индексе для формирования MultiIndex.

Теперь, возвращаясь к вопросу, обратите внимание, что индекс был заменено на df1. Для группового ключа 0.0 индекс исходного фрагмента был [0, 2, 3], тогда как после агрегирования он равен [1, 2, 3]. Однако для df2 исходный индекс был [1, 2, 3], и случайно он не был изменен агрегированием.

...