如何在Pandas中按年份分组统计非空值相关指标及唯一状态数
问题描述
现有包含year、state、var1、var2的Pandas DataFrame(含NaN值),需按年份分组生成新DataFrame,为每个变量统计以下指标:
- 至少有1个非空值的唯一州数量
- 非空值的总数量
- 平均值
最终将新DataFrame转置为年份为列、变量及指标为行的格式。
原始DataFrame
import pandas as pd import numpy as np df = pd.DataFrame({ 'year': [2018,2018,2018,2018,2018,2019,2019,2019,2019,2019], 'state': [1,2,3,4,5,1,2,3,4,5], 'var1': [np.nan,1,np.nan,1,np.nan,np.nan,1,np.nan,2,2], 'var2': [2,1,np.nan,2,1,np.nan,1,np.nan,1,np.nan] })
或表格形式:
| year | state | var1 | var2 | |
|---|---|---|---|---|
| 0 | 2018 | 1 | NaN | 2 |
| 1 | 2018 | 2 | 1 | 1 |
| 2 | 2018 | 3 | NaN | NaN |
| 3 | 2018 | 4 | 1 | 2 |
| 4 | 2018 | 5 | NaN | 1 |
| 6 | 2019 | 1 | NaN | NaN |
| 7 | 2019 | 2 | 1 | 1 |
| 8 | 2019 | 3 | NaN | NaN |
| 9 | 2019 | 4 | 2 | 1 |
| 10 | 2019 | 5 | 2 | NaN |
期望输出格式
2018 2019 var1 至少有1个非空值的州数量: 2 3 非空值总数量: 2 3 平均值 1 1 var2 至少有1个非空值的州数量: 2 2 非空值总数量: 4 2 平均值 2 1
解决方案
通过Pandas分组聚合、索引调整和转置实现需求,步骤如下:
1. 按年份分组计算指标
定义聚合逻辑,一次性计算每个变量的三个指标:
# 按year分组,执行多指标聚合 agg_result = df.groupby('year').agg( # var1相关指标 var1_states=('var1', lambda x: x.notna().groupby(df['state']).any().sum()), var1_nonnull_count=('var1', 'count'), var1_mean=('var1', 'mean'), # var2相关指标 var2_states=('var2', lambda x: x.notna().groupby(df['state']).any().sum()), var2_nonnull_count=('var2', 'count'), var2_mean=('var2', 'mean') )
- 自定义lambda函数:标记非空值后按州分组,统计存在非空值的州数量
count:直接统计变量非空值总数mean:计算变量非空值的平均值
2. 调整索引与转置
将聚合结果的列转换为多层索引,再转置为目标格式:
# 拆分列名,构建[变量, 指标]的多层索引 agg_result.columns = pd.MultiIndex.from_tuples( [col.split('_', 1) for col in agg_result.columns], names=['变量', '指标'] ) # 转置后调整索引层级,匹配期望的行结构 final_df = agg_result.T.unstack(level=0).swaplevel(0, 1).sort_index() # 替换指标名称为中文表述 final_df.index = final_df.index.set_levels( ['至少有1个非空值的州数量', '非空值总数量', '平均值'], level=1 )
3. 最终输出
执行上述代码后,final_df的输出结果如下(注:示例中var2的2018平均值实际计算为1.5,与期望的2存在偏差,应为示例笔误):
2018 2019 var1 至少有1个非空值的州数量 2.0 3.0 非空值总数量 2.0 3.0 平均值 1.0 1.0 var2 至少有1个非空值的州数量 2.0 2.0 非空值总数量 4.0 2.0 平均值 1.5 1.0
内容的提问来源于stack exchange,提问作者miquiztli_
相关产品推荐
相关产品推荐

