Pandas分类频率表不显示0计数及分类变量层级异常咨询
问题分析与解决方案
第一个问题:层级数统计与value_counts结果矛盾的原因
你遇到的核心问题是混淆了「分类变量的预定义层级总数」和「实际观测到的非重复值数量」,而且用来统计层级数的代码len(set(x))并不准确:
len(set(x))统计的是当前列中**实际出现过的非重复值(含NaN,如果存在)**的数量,而非分类变量预先定义的所有层级数。- 如果你用
df['title'].value_counts()得到数百行输出,说明你的title列实际上存在数百个不同的观测值——这要么是你的title列根本不是category类型(可能误判),要么是数据里存在大量看起来相同但实际不同的值(比如带空格、大小写差异的字符串)。
怎么确认?
先检查title列的实际类型:
print(df['title'].dtype)
如果输出是object而非category,说明你之前的select_dtypes(['category'])可能没选中它,或者转换category时出错了。这种情况下,你需要先清洗数据(比如去除空格、统一大小写)再转成category:
# 清洗字符串:去除前后空格、统一小写 df['title'] = df['title'].str.strip().str.lower() # 转换为category类型 df['title'] = df['title'].astype('category')
如果确实是category类型,那你应该用下面的代码统计真正的层级总数(所有预定义类别):
df.select_dtypes(['category']).apply(lambda x: len(x.cat.categories))
这个结果才是分类变量的层级数,而不是len(set(x))。
第二个问题:显示计数为0的分类类别
Pandas的value_counts()默认只显示有计数的类别,要包含所有预定义类别(包括计数为0的),有两种简单方法:
方法1:value_counts() + reindex
# 获取该分类变量的所有预定义类别 all_title_cats = df['title'].cat.categories # 生成包含所有类别的频率表,计数为0的填充为0 title_full_counts = df['title'].value_counts(dropna=False).reindex(all_title_cats, fill_value=0)
方法2:用pd.crosstab
import pandas as pd pd.crosstab(index=df['title'], columns='count', dropna=False)
额外:删除层级数超过53的分类变量
如果你想准确删除层级数超过53的分类变量,应该基于预定义类别总数来筛选,而不是实际观测值数量:
# 统计每个分类变量的层级总数 cat_level_counts = df.select_dtypes(['category']).apply(lambda x: len(x.cat.categories)) # 筛选出层级数<=53的分类变量 keep_cat_cols = cat_level_counts[cat_level_counts <= 53].index.tolist() # 保留这些分类变量,加上非分类变量 df = df[keep_cat_cols + df.select_dtypes(exclude=['category']).columns.tolist()]
内容的提问来源于stack exchange,提问作者NuValue
相关产品推荐
相关产品推荐

