如何用pandas优雅实现非等距成绩区间的人数统计?
成绩自定义分段人数统计的简洁实现方案
你的需求属于标准的自定义分箱场景,分箱本身不要求区间等宽,完全可以用pandas内置的分箱工具实现,不用逐段写冗余的布尔筛选条件。
最优实现方案
用pandas的pd.cut做自定义分箱,所有分段规则集中配置,代码简洁易维护,且向量化运算的性能远高于逐段子集筛选。
完整可运行代码如下:
import pandas as pd # 原始成绩数据 grade_list = [87.5, 87.5, 65.0, 90.0, 72.5, 65.0, 0.0, 65.0, 72.5, 65.0, 72.5, 65.0, 90.0, 90.0, 87.5, 87.5, 87.5, 65.0, 87.5, 65.0, 65.0, 90.0, 99.0, 65.0, 87.5, 65.0, 87.5, 90.0, 87.5, 90.0, 90.0, 0.0, 90.0, 99.0, 65.0, 87.5, 72.5, 72.5, 90.0, 0.0, 65.0, 72.5, 90.0, 90.0, 65.0, 90.0, 90.0, 65.0, 65.0, 0.0, 90.0, 90.0, 100.0, 99.0, 65.0, 90.0, 90.0, 0.0, 99.0, 90.0, 100.0, 87.5, 65.0, 99.0, 0.0, 90.0, 65.0, 90.0, 65.0, 99.0, 90.0, 65.0, 100.0, 65.0, 90.0, 99.0] df = pd.DataFrame({'grade': grade_list}) # 集中配置分段边界和对应分段名称 bins = [-1, 0, 60, 70, 80, 90, 101] labels = [ 'grade == 0', '0 < grade < 60', '60 ≤ grade < 70', '70 ≤ grade < 80', '80 ≤ grade < 90', 'grade ≥ 90' ] # 分箱:right=False指定左闭右开区间,匹配分段规则 df['segment'] = pd.cut(df['grade'], bins=bins, labels=labels, right=False) # 修正边界:将等于0的记录统一归到0分段,解决连续区间无法表示单点匹配的问题 df.loc[df['grade'] == 0, 'segment'] = labels[0] # 按指定顺序输出各分段人数 counts = df['segment'].value_counts().reindex(labels) print(counts)
代码说明
- 所有分段规则都在
bins和labels两个列表中维护,后续调整分段只需要改这两处,不用修改多段筛选逻辑,可维护性远高于逐段判断的写法 pd.cut是pandas内置的向量化分箱工具,数据量越大性能优势越明显,比逐段切片取子集的效率高很多- 针对你给出的示例数据,运行后输出结果如下:
grade == 0 6 0 < grade < 60 0 60 ≤ grade < 70 24 70 ≤ grade < 80 6 80 ≤ grade < 90 13 grade ≥ 90 27 Name: segment, dtype: int64 - 如果需要单独输出某一段的人数,直接按标签索引结果即可,比如执行
print(counts['grade ≥ 90'])就能输出90分及以上的人数。
内容的提问来源于stack exchange,提问作者JJJohn
相关产品推荐
相关产品推荐

