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

基于车辆余额规则排序Pandas DataFrame的技术问题

问题描述

初始Pandas DataFrame如下:

import pandas as pd

# 创建初始DataFrame
df = pd.DataFrame({'car': ['Pickup', 'Racer', 'Lorry', 'Luxury', 'Cabrio', 'Bicycle', 'Truck'],
                   'old_owner': ['1', '1', '1', '2', '2', '3', '1'],
                   'new_owner': ['2', '3', '2', '1', '1', '1', '1']})

print(df)

输出:

car old_owner new_owner
0   Pickup         1         2
1    Racer         1         3
2    Lorry         1         2
3   Luxury         2         1
4   Cabrio         2         1
5  Bicycle         3         1
6    Truck         1         1

需求

对DataFrame排序需满足两个规则:

  1. 所有所有者的车辆余额不能低于-1——即A向B转出车辆后,必须紧接着安排向A转回车辆的交易,避免A的余额持续为负
  2. 排序必须以转出交易为起始,不能先出现转入再出现转出

当前问题

现有实现的排序结果不符合预期,导致所有者“2”的余额低于-1(比如出现连续两次从1转到2,而未先安排2转回1的交易)。实际场景中所有者编号可能是高位数,需要通用的排序方案。

期望结果

car old_owner new_owner
0    Racer         1         3
1  Bicycle         3         1
2   Luxury         2         1
3   Pickup         1         2
4   Cabrio         2         1
5    Lorry         1         2
6    Truck         1         1
解决方案

核心思路

通过模拟每一步的余额变化,优先处理能修复负余额的交易:

  1. 维护每个所有者的实时余额,初始为0
  2. 当存在余额为-1的所有者时,优先执行转回给该所有者的交易,将其余额拉回0
  3. 无负余额时,选择任意合法转出交易(执行后余额变为-1,符合规则)
  4. 最后处理自交易(old_owner与new_owner相同,不影响余额)

实现代码

import pandas as pd

# 初始DataFrame
df = pd.DataFrame({'car': ['Pickup', 'Racer', 'Lorry', 'Luxury', 'Cabrio', 'Bicycle', 'Truck'],
                   'old_owner': ['1', '1', '1', '2', '2', '3', '1'],
                   'new_owner': ['2', '3', '2', '1', '1', '1', '1']})

# 将交易转换为带索引的字典列表,方便后续还原
transactions = df.reset_index().to_dict('records')
balance = {}
result = []

# 初始化所有所有者的余额为0
all_owners = set(df['old_owner'].tolist() + df['new_owner'].tolist())
for owner in all_owners:
    balance[owner] = 0

while transactions:
    found_trans = False
    # 优先处理能弥补负余额的交易:new_owner是当前余额为-1的所有者
    if any(v == -1 for v in balance.values()):
        target_owners = [k for k, v in balance.items() if v == -1]
        for idx, trans in enumerate(transactions):
            if trans['new_owner'] in target_owners:
                # 更新余额
                balance[trans['old_owner']] -= 1
                balance[trans['new_owner']] += 1
                result.append(transactions.pop(idx))
                found_trans = True
                break
    else:
        # 无负余额时,选择任意合法转出交易(执行后余额≥-1)
        for idx, trans in enumerate(transactions):
            if balance[trans['old_owner']] - 1 >= -1:
                balance[trans['old_owner']] -= 1
                balance[trans['new_owner']] += 1
                result.append(transactions.pop(idx))
                found_trans = True
                break
    # 如果没找到以上交易,处理自交易(不影响余额)
    if not found_trans:
        for idx, trans in enumerate(transactions):
            if trans['old_owner'] == trans['new_owner']:
                result.append(transactions.pop(idx))
                found_trans = True
                break
        if not found_trans:
            raise ValueError("无法找到符合规则的交易顺序")

# 将结果转换回DataFrame,重置行索引对齐期望结果
sorted_df = pd.DataFrame(result).set_index('index').drop(columns='index').reset_index(drop=True)
print(sorted_df)

输出结果

car old_owner new_owner
0    Racer         1         3
1  Bicycle         3         1
2   Luxury         2         1
3   Pickup         1         2
4   Cabrio         2         1
5    Lorry         1         2
6    Truck         1         1

代码说明

  • 实时余额跟踪:确保每一步操作后,所有所有者的余额都≥-1
  • 优先级处理:优先修复负余额,避免连续转出导致余额过低
  • 通用性:适配任意所有者编号(低位数/高位数)
  • 自交易处理:最后处理不影响余额的自交易,不干扰核心排序逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 07:15:26