pandas 分组依据子集 returns 错误的行数

pandas group by on a subset returns wrong number of rows

我正在极大地简化这个问题(与初稿相比)。

给定一个具有分类类型的数据框,如果我对数据框进行子集化,使其仅包含一些分类值,子集化的数据框仍会记住类别级别的完整列表。

当我 groupby 在这个较小的数据框上时,我继续得到我不期望的值。

下面是一些复制此代码的代码:

import pandas as pd

df = pd.DataFrame({
    'colA':['a', 'b', 'b', 'c', 'c', 'c'], 
    'colB':1
})
df['colA'] = df['colA'].astype('category') #<= this is important
df

输出

    colA    colB
0   a   1
1   b   1
2   b   1
3   c   1
4   c   1
5   c   1
df.groupby('colA').max()

输出

colB
colA    
a   1
b   1
c   1
smalldf = df.iloc[:3]
smalldf['colA']

输出

0    a
1    b
2    b
Name: colA, dtype: category
Categories (3, object): ['a', 'b', 'c']

注意上面 'c' 仍然在分类级别

smalldf.groupby('colA').max()

输出

    colB
colA    
a   1.0
b   1.0
c   NaN

这里的这个'c'出乎意料。但是,我想这可以解释清楚,因为子集化不会删除类别级别。

当你写出较小的数据帧时,问题会变得更糟

FEATHER_PATH = Path.joinpath(Path.home(), 'Downloads', 'test.feather')
smalldf.to_feather(FEATHER_PATH)

pd.read_feather(FEATHER_PATH)['colA']
0    a
1    b
2    b
Name: colA, dtype: category
Categories (3, object): ['a', 'b', 'c']

假设你写出较小的数据框并将其传递给某人。他们查看了文件,只看到了 'a' 和 'b' 的 colA 个值。但是,当他们进行 groupby 时,会出现 'c'。 'c'在实际数据中找不到!

他们必须明确地寻找类别级别才能找到隐藏在其中的 'c'!

我不确定这种行为是否错误,但肯定会非常混乱!

不确定是否可以将其留在这里作为对其他人的警告。

这是正确的,基于 groups.get_group('colA') 的 DataFrame 的长度将与 'colA' 列的唯一值具有相同的长度。

编辑:假定 'colA' 是您最大的列。

没有错,只是在文档中有点隐藏。你可以找到它,例如 here:

DataFrame methods like DataFrame.sum() also show “unused” categories.

Groupby will also show “unused” categories

关于 writing/reading:没有它你会丢失类型信息,这也可能会造成伤害。所以需要权衡取舍。

您应该可以使用 .groupby()observed=True 选项来处理它:

observed: bool, default False

This only applies if any of the groupers are Categoricals. If True: only show observed values for categorical groupers. If False: show all values for categorical groupers.

例如:

smalldf.groupby('colA', observed=True).max()

交付

      colB
colA      
a        1
b        1