You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas实现自定义多规则排序并封装为可复用函数

pandas按自定义规则排序分组列实现方案

问题背景

现有如下结构的pandas DataFrame:

PLAYER      GRP
Mike        F3.03
Max         F2.01
El          G7.99
Billy       G7.09
Steve       B13.99
Vecna       F3.03

需要按grp列做升序排序,排序优先级从高到低为:

  • 字段开头的字母
  • 小数点前的数字
  • 小数点后的数字
    当grp取值完全相同时,按player列升序排列。实际场景中小数点后的数字存在前导零,小数点前的数字无前导零,期望排序结果如下:
PLAYER      GRP
Steve       B13.99
Max         F2.01
Mike        F3.03
Vecna       F3.03
Billy       G7.09
El          G7.99

要求将排序逻辑封装为可复用函数,适配所有包含同结构分组列的DataFrame。
示例数据初始化代码:

import pandas as pd
df = pd.DataFrame({'player': ['Mike', 'Max', 'El', 'Billy', 'Steve', 'Vecna'], 
                   'grp': ['F3.03', 'F2.01', 'G7.99', 'G7.09', 'B13.99', 'F3.03']})

实现代码

核心思路是通过正则拆分grp列的三个排序维度,数字部分转为整数解决前导零比较问题,再调用pandas原生sort_values完成多键排序,封装为通用函数:

import re
import pandas as pd

def sort_grp_df(df: pd.DataFrame, grp_col: str = 'grp', name_col: str = 'player') -> pd.DataFrame:
    """
    按自定义规则对带分组列的DataFrame排序
    参数:
        df: 待排序原始DataFrame
        grp_col: 分组列列名,默认值为'grp'
        name_col: 分组重复时用于排序的名称列列名,默认值为'player'
    返回:
        排序完成、结构与原表一致的DataFrame
    """
    def _parse_grp(grp_val: str):
        # 正则匹配拆分首字母、小数点前数字、小数点后数字
        parts = re.match(r'([A-Za-z]+)(\d+)\.(\d+)', grp_val)
        if not parts:
            raise ValueError(f"值 {grp_val} 不符合分组列格式要求")
        letter, num_pre, num_post = parts.groups()
        # 数字转整数,自动处理前导零的数值比较逻辑
        return letter, int(num_pre), int(num_post)
    
    df_work = df.copy()
    # 生成三个临时排序键
    df_work[['_sort_letter', '_sort_pre', '_sort_post']] = df_work[grp_col].apply(_parse_grp).tolist()
    # 按优先级排序后删除临时列
    df_res = df_work.sort_values(
        by=['_sort_letter', '_sort_pre', '_sort_post', name_col],
        ascending=True,
        ignore_index=True
    ).drop(columns=['_sort_letter', '_sort_pre', '_sort_post'])
    return df_res

# 测试调用
if __name__ == "__main__":
    df = pd.DataFrame({'player': ['Mike', 'Max', 'El', 'Billy', 'Steve', 'Vecna'], 
                       'grp': ['F3.03', 'F2.01', 'G7.99', 'G7.09', 'B13.99', 'F3.03']})
    print(sort_grp_df(df))

说明

  • 正则匹配逻辑兼容首字母长度大于1的场景,后续如果出现类似AB12.03格式的分组值也能正常排序
  • 数字部分统一转为整数类型比较,无需额外处理前导零,比如G7.09和G7.99比较时,9<99,排序结果符合预期
  • 函数支持自定义列名传入,如果实际表中分组列叫Group、人员列叫PLAYER,直接调用sort_grp_df(df, grp_col='Group', name_col='PLAYER')即可复用
  • 测试运行输出结果和期望完全一致:
player     grp
0  Steve  B13.99
1    Max   F2.01
2   Mike   F3.03
3  Vecna   F3.03
4  Billy   G7.09
5     El   G7.99

内容的提问来源于stack exchange,提问作者DJC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 11:57:13