Pandas:为分类数据补0以实现全维度频次统计
解决方案:为缺失分类项自动补0的通用方法
这是个非常典型的统计需求——要确保所有预设的分类标签都出现在结果中,不管对应的数据是否存在。针对你的场景,我有两种简洁且通用的方法,完全适配星期几、月份、年份或任何自定义分类数组:
方法1:利用pd.Categorical提前定义分类(推荐)
这种方法从根源上解决问题,在生成分类列时就指定好所有需要的标签和顺序,分组时会自动保留所有分类,缺失项直接统计为0:
import numpy as np import pandas as pd # 模拟数据 data = {'date': ["2000-01-01", "2000-05-01", "2000-11-11", "2000-11-01"], 'col_2': ['a', 'b', 'c', 'd']} df = pd.DataFrame.from_dict(data) # 日期转换 df['date'] = pd.to_datetime(df['date']) # 定义完整的星期几分类(法语) JOUR_SEMAINE = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"] # 关键:将day_of_week转为指定分类类型,确保顺序和完整性 df['day_of_week'] = pd.Categorical( df['date'].dt.day_name(locale='fr_FR'), categories=JOUR_SEMAINE, ordered=True ) # 分组统计:observed=False确保保留所有分类项(pandas 1.1+支持) result = df.groupby('day_of_week', observed=False)['day_of_week'].count().reset_index(name='count') print(result)
输出结果正好是你想要的:
day_of_week count 0 Lundi 1 1 Mardi 0 2 Mercredi 1 3 Jeudi 0 4 Vendredi 0 5 Samedi 2 6 Dimanche 0
为什么这方法通用?
只需要把JOUR_SEMAINE替换成你的目标分类数组即可:
- 比如法语月份:
MOIS = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"] - 或者自定义业务标签:
STATUS = ["En cours", "Terminé", "Annulé"]
方法2:用reindex补全已分组的结果
如果已经有了分组后的统计数据,也可以通过重新索引的方式快速补全缺失项:
# 你的原有代码(生成分组后的data) df['date'] = pd.to_datetime(df['date']) df['day_of_week'] = df['date'].dt.day_name(locale='fr_FR') data = df.groupby('day_of_week')['day_of_week'].agg(['count']).reset_index() # 通用补全步骤 JOUR_SEMAINE = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"] result = data.set_index('day_of_week').reindex(JOUR_SEMAINE, fill_value=0).reset_index() print(result)
这种方法的逻辑是:把分组结果的索引切换为分类列,用预设的完整分类数组重新索引,缺失的位置用fill_value=0填充,最后再把索引转回普通列。
两种方法的对比
- 方法1更高效,一步到位,适合从原始数据开始处理的场景;
- 方法2更灵活,适合已经有部分统计结果,需要补全的场景。
内容的提问来源于stack exchange,提问作者Richnou
相关产品推荐
相关产品推荐

