在Pandas GroupBy分组内对成绩等级字母排序的问题
解决分组内成绩等级的指定规则排序问题
首先明确需求:在Gender分组内,按照**成绩等级带+的优先,其次是无符号,最后是带-**的规则排序(例如B+ > B > B-,C+ > C > C-,同时A-这类等级按字母顺序在B类之前)。
错误原因分析
- 第一种方法报错是因为
sort_values的key参数接收的是整个Series,直接调用x.endswith()会触发错误——Series没有这个方法,必须对每个元素单独处理。 - 第二种方法无效是因为你对
Gender列应用排序函数,而非目标列Scored Grade,且未处理分组内的排序逻辑。
正确实现方式
方法一:生成排序键后组内排序
先为每个Scored Grade生成对应的排序元组,再按Gender分组后对目标列排序:
import pandas as pd # 先完成分组统计,重命名计数列 df2 = df.groupby(['Gender', 'Scored Grade']).size().reset_index(name='Count') # 定义生成排序键的函数 def get_sort_key(grade): letter = grade[0] # 提取成绩字母部分,如A-取A、B+取B # 符号优先级:+ > 无符号 > -,用数值映射:+对应-1,无符号对应0,-对应1 sign = -1 if '+' in grade else 1 if '-' in grade else 0 return (letter, sign) # 按Gender分组,每组内按Scored Grade的排序键排序 df_sorted = df2.groupby('Gender', group_keys=False).apply( lambda g: g.sort_values(by='Scored Grade', key=lambda x: x.apply(get_sort_key)) ).reset_index(drop=True)
方法二:使用Categorical类型指定顺序(更直观)
提前定义所有成绩等级的优先级顺序,将Scored Grade转为Categorical类型,排序时会自动遵循指定顺序:
import pandas as pd # 按规则整理成绩等级的完整顺序 grade_order = ['A-', 'B+', 'B', 'B-', 'C+', 'C', 'C-'] # 分组统计得到结果集 df2 = df.groupby(['Gender', 'Scored Grade']).size().reset_index(name='Count') # 将Scored Grade转为有序分类类型 df2['Scored Grade'] = pd.Categorical(df2['Scored Grade'], categories=grade_order, ordered=True) # 按Gender和Scored Grade排序 df_sorted = df2.sort_values(by=['Gender', 'Scored Grade']).reset_index(drop=True)
方法三:分组统计前先排序原始数据
如果原始数据量不大,可先按规则排序,再分组统计,结果自然是组内有序的:
import pandas as pd def get_sort_key(grade): letter = grade[0] sign = -1 if '+' in grade else 1 if '-' in grade else 0 return (letter, sign) # 对原始数据按Gender和Scored Grade规则排序 df_sorted_raw = df.sort_values( by=['Gender', 'Scored Grade'], key=lambda x: x.apply(get_sort_key) if x.name == 'Scored Grade' else x ) # 分组统计,关闭默认排序保证结果有序 df_result = df_sorted_raw.groupby(['Gender', 'Scored Grade'], sort=False).size().reset_index(name='Count')
最终效果示例
以你的数据为例,处理后Female组的顺序为:
Gender Scored Grade Count 0 Female A- 1 1 Female B+ 4 2 Female B 4 3 Female B- 9 4 Female C+ 4 5 Female C 3
Male组的顺序为:
Gender Scored Grade Count 6 Male B+ 4 7 Male B 8 8 Male B- 9 9 Male C+ 8 10 Male C 5 11 Male C- 1
内容的提问来源于stack exchange,提问作者Khalil Al Hooti
相关产品推荐
相关产品推荐

