You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas中Categorical类型过滤后value_counts返回0计数类别原因咨询

问题:过滤分类列后value_counts仍显示原全类别?

操作步骤与现象

1. 创建带分类列的DataFrame

df = pd.DataFrame({'years': [2015, 2016, 2017,2017, 2018, 2019, 2019, 2020]})
df['years'] = df['years'].astype('category')
print(df.dtypes)
# years    category
# dtype: object

2. 过滤得到子数据集

subset_years = [2015, 2016, 2017, 2018]
subset_df = df[df['years'].isin(subset_years)]
print(subset_df)
#    years
# 0   2015
# 1   2016
# 2   2017
# 3   2017
# 4   2018

3. 方法结果差异

  • 调用unique():
subset_df.years.unique()
# [2015, 2016, 2017, 2018]
# Categories (4, int64): [2015, 2016, 2017, 2018]
  • 调用value_counts():
subset_df.years.value_counts()
# 2015    1
# 2016    1
# 2017    2
# 2018    1
# 2019    0
# 2020    0
# Name: years, dtype: int64

疑问:已对years列进行过滤,为何value_counts()仍返回2019、2020且计数为0?这些类别不应在过滤后被移除吗?

原因解释

Pandas的分类类型(category)会保留原始数据集的完整类别集合,即便过滤出子数据集,分类列的类别体系不会自动收缩——这是分类类型的设计特性,用于维护统一的类别标准,方便后续的数据集合并、类别对比等操作。

  • unique()方法仅返回子数据集中实际存在的类别,因此不会显示2019、2020;
  • value_counts()默认会遍历分类列的所有原始类别,对不存在的类别计数设为0。

解决方法

方法1:移除未使用的类别

对过滤后的分类列调用cat.remove_unused_categories(),重置为仅包含当前子数据集中存在的类别:

subset_df['years'] = subset_df['years'].cat.remove_unused_categories()
subset_df.years.value_counts()
# 2017    2
# 2015    1
# 2016    1
# 2018    1
# Name: years, dtype: int64

方法2:调整value_counts参数(Pandas >=1.3.0)

使用include_empty=False参数,让value_counts()仅统计子数据集中实际存在的类别:

subset_df.years.value_counts(include_empty=False)
# 2017    2
# 2015    1
# 2016    1
# 2018    1
# Name: years, dtype: int64

内容的提问来源于stack exchange,提问作者floss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 10:30:45