
本文详解如何在 Pandas 中对指定列进行分组,并精确统计每组中另一列的非缺失值(non-null)数量,尤其解决默认 value_counts() 无法体现“零计数”类别的常见痛点。
本文详解如何在 pandes 中对指定列进行分组,并精确统计每组中另一列的**非缺失值(non-null)数量**,尤其解决默认 `value_counts()` 无法体现“零计数”类别的常见痛点。
在 Pandas 数据分析中,value_counts() 是快速获取某列频次分布的常用方法,但它仅作用于单列,且天然忽略缺失值(NaN)的存在语义——即它只统计该列自身的非空值出现次数,无法反映“某组内其他列是否为空”的业务逻辑。例如,当需要统计每个 ColA 类别下 ColB 的有效记录数(含 NaN 视为无效),而 ColA='D' 对应的 ColB=NaN 时,df.ColA.value_counts() 仍会返回 D: 1,这显然不符合“按 ColA 分组、统计 ColB 有效值个数”的真实需求。
正确做法是使用 groupby + count() 组合:
count() 在 Series 或 DataFrame 的列上被调用时,默认仅统计非空(non-null)值的数量,且能自然保留所有分组键(包括那些对应全空值的组),从而实现“零计数”的显式表达。
以下为完整示例:
import pandas as pd
import numpy as np
# 构造示例数据
df = pd.DataFrame({
'ColA': ['A', 'A', 'B', 'B', 'C', 'D'],
'ColB': ['01', '02', '03', '04', '05', np.nan]
})
# ✅ 正确:按 ColA 分组,统计 ColB 的非空值数量
result = df.groupby('ColA', as_index=False)['ColB'].count()
print(result)输出:
ColA ColB 0 A 2 1 B 2 2 C 1 3 D 0
? 关键说明:
- df.groupby('ColA', as_index=False) 确保结果为 DataFrame(而非默认的 Series with MultiIndex),便于后续处理;
- ['ColB'].count() 明确指定对 ColB 列计数,自动跳过 NaN;
- 即使 ColA='D' 对应的 ColB 全为 NaN,该组仍保留在结果中,计数值为 0。
⚠️ 注意事项:
- 不要误用 size():df.groupby('ColA')['ColB'].size() 返回的是每组总行数(含 NaN),本例中 D 组结果为 1,不符合要求;
- 避免链式 value_counts():df.dropna(subset=['ColB']).ColA.value_counts() 会直接丢弃 D 行,导致 D 缺失;
- 若需多列统计,可扩展为:df.groupby('ColA')[['ColB', 'ColC']].count(),各列独立计算非空值数量。
总结:当目标是“按某列分组 + 统计另一列的有效观测数”,务必选用 groupby(...)[col].count() 模式。它语义清晰、行为确定、结果完整,是 Pandas 中处理带缺失值分组计数任务的标准范式。










