Pandas在groupby函数中计算空值数量

44
df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'],
               'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
               'C' : [np.nan, 'bla2', np.nan, 'bla3', np.nan, np.nan, np.nan, np.nan]})

输出:

     A      B     C
0  foo    one   NaN
1  bar    one  bla2
2  foo    two   NaN
3  bar  three  bla3
4  foo    two   NaN
5  bar    two   NaN
6  foo    one   NaN
7  foo  three   NaN
我想使用groupby来统计不同foo组合中NaN的数量。 期望的输出(编辑):
     A      B     C    D
0  foo    one   NaN    2
1  bar    one  bla2    0
2  foo    two   NaN    2
3  bar  three  bla3    0
4  foo    two   NaN    2
5  bar    two   NaN    1
6  foo    one   NaN    2
7  foo  three   NaN    1

目前我正在尝试这个:

df['count']=df.groupby(['A'])['B'].isnull().transform('sum')

但这并不起作用...

谢谢

3个回答

53

我认为你需要使用groupbysum函数来处理NaN值:

df2 = df.C.isnull().groupby([df['A'],df['B']]).sum().astype(int).reset_index(name='count')
print(df2)
     A      B  count
0  bar    one      0
1  bar  three      0
2  bar    two      1
3  foo    one      2
4  foo  three      1
5  foo    two      2

注意,.isnull() 是应该用在原始数据框列上的,而不是 groupby() 对象上。 groupby() 没有 .isnull(),但如果有的话,它应该会给出与在原始 DataFrame 上使用 .isnull() 相同的结果。

如果需要过滤,请先添加布尔索引

df = df[df['A'] == 'foo']
df2 = df.C.isnull().groupby([df['A'],df['B']]).sum().astype(int)
print(df2)
A    B    
foo  one      2
     three    1
     two      2

或者更简单:

df = df[df['A'] == 'foo']
df2 = df['B'].value_counts()
print(df2)
one      2
two      2
three    1
Name: B, dtype: int64

编辑:解决方案非常相似,只需添加transform

df['D'] = df.C.isnull().groupby([df['A'],df['B']]).transform('sum').astype(int)
print(df)
     A      B     C  D
0  foo    one   NaN  2
1  bar    one  bla2  0
2  foo    two   NaN  2
3  bar  three  bla3  0
4  foo    two   NaN  2
5  bar    two   NaN  1
6  foo    one   NaN  2
7  foo  three   NaN  1

类似的解决方案:

df['D'] = df.C.isnull()
df['D'] = df.groupby(['A','B'])['D'].transform('sum').astype(int)
print(df)
     A      B     C  D
0  foo    one   NaN  2
1  bar    one  bla2  0
2  foo    two   NaN  2
3  bar  three  bla3  0
4  foo    two   NaN  2
5  bar    two   NaN  1
6  foo    one   NaN  2
7  foo  three   NaN  1

那个回答完美地解决了我的初始问题,但我刚刚意识到我的“期望答案”是错误的。对此感到抱歉。我需要将结果添加到初始数据框中。 - Stefan
1
.reset_index(name='count') 中的 name 参数似乎不被支持:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.reset_index.html - jmatsen

34
df[df.A == 'foo'].groupby('b').agg({'C': lambda x: x.isnull().sum()})

返回:

=>        C
B       
one    2
three  1
two    2

3
在pandas中,这是我认为最简洁的解决方案。顺便提一下,在R的data.table中,它只是 df[A=='foo', sum(is.na(C)), b] - yImI

3

只需添加参数dropna=False

df.groupby(['A', 'B','C'], dropna=False).size()

请查看文档: dropnabool,默认为True 如果为True,并且组键包含NA值,则NA值将与行/列一起被删除。如果为False,则NA值也将被视为组中的键。


这种行为是我正在寻找的——基本上就是与 R 的 table(..., useNA = 'ifany') 一致的东西。 - srvanderplas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接