基于行交换的DataFrame排序算法:实现特定账户排序规则
问题与解决方案
示例DataFrame
import pandas as pd data = { 'address': [1234, 24389, 4384, 4484, 1234, 24389, 4384, 188], 'old_account': [200, 200, 200, 300, 200, 494, 400, 100], 'new_account': [300, 100, 494, 200, 400, 200, 200, 200] } df = pd.DataFrame(data) print(df)
输出结果:
address old_account new_account 0 1234 200 300 1 24389 200 100 2 4384 200 494 3 4484 300 200 4 1234 200 400 5 24389 494 200 6 4384 400 200 7 188 100 200
排序需求
A) 基础配对规则
要求old_account为200的行,下一行必须是new_account为200的行,形成固定配对格式:
200 xxx xxx 200
B) 非200值的处理顺序
需按指定顺序处理非200的账户值:先处理所有和300相关的行,格式如下:
200 300 300 200
处理完300的所有相关行后,再依次处理下一个值(如100、494、400),最终排序后的DataFrame如下:
address old_account new_account 0 1234 200 300 1 4484 300 200 2 24389 200 100 3 188 100 200 4 4384 200 494 5 24389 494 200 6 1234 200 400 7 4384 400 200
现有代码的问题
现有代码仅能满足需求A,但无法按指定顺序处理非200值的配对,代码如下:
import pandas as pd # Create the initial DataFrame df= pd.read_csv('dummy_data.csv', sep=';') # Initiate sorted df sorted_df = pd.DataFrame(columns=df.columns) while not df.empty: # Find the first row where '200' is in 'old_account' idx_old = df.index[df['old_account'] == 200].min() if pd.notna(idx_old): # Add the corresponding row to the sorted result sorted_df = pd.concat([sorted_df, df.loc[[idx_old]]], ignore_index=True) # Remove the row from the original DataFrame df = df.drop(index=idx_old) # Find the matching row where '200' is in 'new_account' idx_new = df.index[df['new_account'] == 200].min() if pd.notna(idx_new): # Add the corresponding row to the sorted result sorted_df = pd.concat([sorted_df, df.loc[[idx_new]]], ignore_index=True) # Remove the row from the original DataFrame df = df.drop(index=idx_new) else: break # If no matching row is found, exit the loop else: break # If no more '200' in 'old_account' is found, exit the loop # Reset the index of the sorted DataFrame sorted_df.reset_index(drop=True, inplace=True) print(sorted_df)
解决方案代码
要同时满足A和B的需求,可先提取所有非200的目标值并按指定顺序排序,再逐个处理每个值的配对:
import pandas as pd # 初始化DataFrame(若从文件读取,替换为pd.read_csv即可) data = { 'address': [1234, 24389, 4384, 4484, 1234, 24389, 4384, 188], 'old_account': [200, 200, 200, 300, 200, 494, 400, 100], 'new_account': [300, 100, 494, 200, 400, 200, 200, 200] } df = pd.DataFrame(data) # 定义非200值的处理顺序(可根据需求调整) target_values = [300, 100, 494, 400] sorted_df = pd.DataFrame(columns=df.columns) # 遍历每个目标值,处理对应的配对 for val in target_values: # 筛选old_account=200且new_account=当前目标值的行 mask_old = (df['old_account'] == 200) & (df['new_account'] == val) while mask_old.any(): # 取第一个符合条件的行加入结果 idx_old = df.index[mask_old].min() sorted_df = pd.concat([sorted_df, df.loc[[idx_old]]], ignore_index=True) df = df.drop(idx_old) # 筛选对应的new_account=200且old_account=当前目标值的行 mask_new = (df['new_account'] == 200) & (df['old_account'] == val) if mask_new.any(): idx_new = df.index[mask_new].min() sorted_df = pd.concat([sorted_df, df.loc[[idx_new]]], ignore_index=True) df = df.drop(idx_new) # 更新筛选条件,适配已修改的DataFrame mask_old = (df['old_account'] == 200) & (df['new_account'] == val) # 重置结果的索引 sorted_df.reset_index(drop=True, inplace=True) print(sorted_df)
代码说明
- 先指定非200值的处理顺序
target_values,确保按需求优先级处理 - 对每个目标值,先匹配
old_account=200且new_account=目标值的行,加入结果后再匹配对应的old_account=目标值且new_account=200的行完成配对 - 循环处理直到该目标值的所有配对完成,再切换到下一个目标值
内容的提问来源于stack exchange,提问作者Exa
相关产品推荐
相关产品推荐

