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

如何用Pandas高效处理大规模排序有序列表(ROL)数据

大规模排序有序列表(ROL)跨周期对比高效处理方案

问题背景

  • 处理大规模**排序有序列表(ROL)**数据,需跨周期比较个体对机构/项目的排名变化
  • ROL定义:个体提交的报告,按偏好从高到低(0为最偏好)对机构下的项目排序
  • 需执行的操作:对比ROL间的排名变化、识别新增机构/项目等
  • 当前困境:原用Pandas+字典处理,50万个体耗时约20小时,子样本甚至耗时28小时,急需提速

原实现代码

import pandas as pd
import numpy as np

# 生成测试数据集
df = pd.DataFrame([[1, 1, 0, 100, 101], [1, 2, 0, 100, 101], [1, 2, 1, 100, 102], [2, 1, 0, 100, 101], [2, 2, 0, 100, 101], [2, 2, 1, 200, 202], [3, 1, 0, 100, 101], [3, 1, 1, 200, 201], [3, 2, 0, 100, 101], [3, 2, 1, 200, 201], [4, 1, 0, 100, 101], [4, 1, 1, 200, 201], [4, 2, 0, 200, 201], [4, 2, 1, 100, 101] ], columns=['id_individual', 'period', 'rank', 'id_institution', 'id_program'])


df['change_app'] = False 
df['change_order'] = False
df['add_newinst'] = False
df['add_newprog'] = False

for indiv in df['id_individual'].unique():

    # 获取个体各周期的排名数据    
    r_pre = df.loc[(df['id_individual'] == indiv) & (df['period'] == 1)]
    r_post = df.loc[(df['id_individual'] == indiv) & (df['period'] == 2)] 
    
    # 生成存储排名的字典
    rank_pre = {}
    rank_post = {}

    # 提取机构和项目信息存入字典
    for i in range(0, len(r_pre)):
        rank_pre[i] = r_pre['id_institution'].loc[r_pre['rank'] == i].values[0], r_pre['id_program'].loc[r_pre['rank'] == i].values[0]

    for i in range(0, len(r_post)):
        rank_post[i] = r_post['id_institution'].loc[r_post['rank'] == i].values[0], r_post['id_program'].loc[r_post['rank'] == i].values[0]
    

    # 若前后周期排名字典不同,计算各类变化
    if rank_pre != rank_post:
        # 标记整体申请变化
        df['change_app'].loc[(df['id_individual'] == indiv)] = True

        # 标记是否仅为排序变化(项目/机构集合一致、数量相同)
        df['change_order'].loc[(df['id_individual'] == indiv)] = (set(rank_pre.values()) == set(rank_post.values())) & (len(rank_pre) == len(rank_post))

        # 提取机构和项目集合
        programs_pre = set(rank_pre.values())
        programs_post = set(rank_post.values())

        inst_pre = set([x[0] for x in rank_pre.values()])
        inst_post = set([x[0] for x in rank_post.values()]) 

        # 标记是否新增机构
        df['add_newinst'].loc[(df['id_individual'] == indiv)] = len(inst_post - inst_pre) > 0

        # 标记是否新增项目
        df['add_newprog'].loc[(df['id_individual'] == indiv)] = len(programs_post - programs_pre) > 0

df.head(14)

预期输出

id_individual  period  rank  id_institution  id_program  change_app  change_order  add_newinst  add_newprog
0               1       1     0             100         101        True         False        False         True
1               1       2     0             100         101        True         False        False         True
2               1       2     1             100         102        True         False        False         True
3               2       1     0             100         101        True         False         True         True
4               2       2     0             100         101        True         False         True         True
5               2       2     1             200         202        True         False         True         True
6               3       1     0             100         101       False         False        False        False
7               3       1     1             200         201       False         False        False        False
8               3       2     0             100         101       False         False        False        False
9               3       2     1             200         201       False         False        False        False
10              4       1     0             100         101        True          True        False        False
11              4       1     1             200         201        True          True        False        False
12              4       2     0             200         201        True          True        False        False
13              4       2     1             100         101        True          True        False        False

高效优化方案

原代码的核心问题是嵌套循环+多次切片查询,严重拖慢性能。优化思路是利用Pandas的向量化操作、分组聚合,避免逐个体循环,大幅减少IO操作。

优化后代码

import pandas as pd
import numpy as np

# 生成测试数据集
df = pd.DataFrame([[1, 1, 0, 100, 101], [1, 2, 0, 100, 101], [1, 2, 1, 100, 102], [2, 1, 0, 100, 101], [2, 2, 0, 100, 101], [2, 2, 1, 200, 202], [3, 1, 0, 100, 101], [3, 1, 1, 200, 201], [3, 2, 0, 100, 101], [3, 2, 1, 200, 201], [4, 1, 0, 100, 101], [4, 1, 1, 200, 201], [4, 2, 0, 200, 201], [4, 2, 1, 100, 101] ], columns=['id_individual', 'period', 'rank', 'id_institution', 'id_program'])

# 1. 对每个个体+周期,生成排序后的(机构,项目)元组列表和集合
def aggregate_rol(group):
    # 按rank升序排序,保证顺序正确
    sorted_group = group.sort_values('rank')
    # 生成有序的(机构,项目)元组列表
    rol_list = list(zip(sorted_group['id_institution'], sorted_group['id_program']))
    # 生成项目集合、机构集合
    prog_set = set(rol_list)
    inst_set = set(x[0] for x in rol_list)
    return pd.Series({
        'rol_list': rol_list,
        'prog_set': prog_set,
        'inst_set': inst_set,
        'rol_len': len(rol_list)
    })

# 分组聚合,得到每个个体各周期的ROL特征
rol_features = df.groupby(['id_individual', 'period']).apply(aggregate_rol).unstack()

# 2. 提取前后周期的特征,计算各类变化
rol_features['change_app'] = rol_features['rol_list'][1] != rol_features['rol_list'][2]
rol_features['change_order'] = (rol_features['prog_set'][1] == rol_features['prog_set'][2]) & (rol_features['rol_len'][1] == rol_features['rol_len'][2]) & rol_features['change_app']
rol_features['add_newinst'] = rol_features['inst_set'][2].difference(rol_features['inst_set'][1]).apply(len) > 0
rol_features['add_newprog'] = rol_features['prog_set'][2].difference(rol_features['prog_set'][1]).apply(len) > 0

# 3. 将结果合并回原DataFrame
result_df = df.merge(
    rol_features[['change_app', 'change_order', 'add_newinst', 'add_newprog']].reset_index(),
    on='id_individual',
    how='left'
)

# 重置列名(unstack后列名是多级,合并后需要调整)
result_df.columns = [col if not isinstance(col, tuple) else col[0] for col in result_df.columns]

print(result_df.head(14))

优化点说明

  • 避免逐个体循环:用groupby.apply一次性完成所有个体的ROL特征提取,利用Pandas的C级优化代替Python级循环
  • 向量化对比:直接对聚合后的Series做元素级对比,无需逐个体判断
  • 减少重复查询:一次分组聚合即可获取所有需要的集合、列表数据,避免原代码中多次loc切片查询
  • 排序保证一致性:聚合时显式按rank排序,确保ROL顺序的正确性

性能提升效果

该方案将时间复杂度从O(N*M)(N为个体数,M为每个个体的项目数)降低至O(K log K)(K为总数据行数,排序的时间复杂度),对于50万个体的数据集,耗时可压缩至分钟级。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 14:35:19