Pandas 忽略 dropna=False 和 groupby() 中的分类列

buh*_*htz 7 python pandas pandas-groupby

我想在使用时包含默认情况下不会发生的NA值。groupby()我认为这个选项dropna=False让它发生。但当列是类型时,Categorical该选项不起作用。

我认为最好的人会说这背后有一个深思熟虑的设计决策。或者可能与我不完全理解的pandas bug有关?

我这里使用的 pandas 版本是1.2.5.

#!/usr/bin/env python3
import pandas as pd

print(pd.__version__)  # 1.2.5

# initial data
df = pd.DataFrame(
    {
        '2019': [1, pd.NA, 0],
        'N': [2, 0, 7],
    }
)
print(df)

## groupby()'s working as expected

# without NA
res = df.groupby('2019').size()
print(f'\n{res}')

# include NA
res = df.groupby('2019', dropna=False).size()
print(f'\n{res}')

## now the problems
## convert to Category
df['2019'] = df['2019'].astype('category')

# PROBLEM: NA is ignored
res = df.groupby('2019', dropna=False).size()
print(f'\n{res}')

# PROBLEM: NA is ignored even observed has no effect
res = df.groupby('2019', dropna=False, observed=True).size()
print(f'\n{res}')
Run Code Online (Sandbox Code Playgroud)

在输出中,您首先看到初始 DataFrame,然后看到两个表现符合预期的 groupby() 输出。但最后两个 groupby() 输出说明了我的问题。

1.2.5
   2019  N
0     1  2
1  <NA>  0
2     0  7

2019
0    1
1    1
dtype: int64

2019
0.0    1
1.0    1
NaN    1
dtype: int64

2019
0    1
1    1
dtype: int64

2019
1    1
0    1
dtype: int64
>>>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
Run Code Online (Sandbox Code Playgroud)

Mic*_*ter 3

这是一个错误。它已被修复并将在 pandas 2.0 中发布。

最简单的解决方法是暂时撤消类别:

orig = df['2019'].cat.categories.dtype
if np.issubdtype(orig, np.integer) or orig == 'bool':
    orig = 'Int64'  # Allow NA values.
res = df.astype({'2019': orig}).groupby('2019', dropna=False, observed=True).size()
Run Code Online (Sandbox Code Playgroud)