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

如何在Pandas中按自定义关联规则排序行并处理同日期场景?

用Python/Pandas实现值转换日志的拓扑排序

原始样本数据

id  nv  ov        date
  1   1   0  01/02/2023
  1   2   1  01/02/2023
  1   5   4  01/03/2023
  1   1   3  01/02/2023
  1   4   1  01/02/2023
  1   3   2  01/02/2023
  1   6   5  01/03/2023
  1   7   6  01/04/2023
  1   7   7  01/04/2023

字段说明:

  • nv:新值(new value)
  • ov:旧值(old value)

排序规则

  • ov为null(或样本中的0)的行必须排在最前面
  • 排序后需满足:前一行的nv等于当前行的ov
  • 当有多个匹配项时,选择能覆盖所有转换记录的路径(例如(1,0)之后优先选(2,1)而非(4,1))
  • 同一日期内的多条记录需遵循上述转换逻辑排序

Pandas实现方案

可以通过构建转换拓扑图+深度优先遍历的方式实现,代码如下:

import pandas as pd

# 1. 加载原始数据
data = [
    [1, 1, 0, "01/02/2023"],
    [1, 2, 1, "01/02/2023"],
    [1, 5, 4, "01/03/2023"],
    [1, 1, 3, "01/02/2023"],
    [1, 4, 1, "01/02/2023"],
    [1, 3, 2, "01/02/2023"],
    [1, 6, 5, "01/03/2023"],
    [1, 7, 6, "01/04/2023"],
    [1, 7, 7, "01/04/2023"],
]
df = pd.DataFrame(data, columns=["id", "nv", "ov", "date"])

# 2. 构建转换映射:按ov分组,先按日期+nv排序保证遍历优先级
df_sorted = df.sort_values(by=["date", "nv"], ignore_index=True)
transition_map = df_sorted.groupby("ov")["nv"].apply(list).to_dict()

# 3. 深度优先遍历拓扑图,覆盖所有转换路径
visited = set()
result_order = []

def dfs(current_nv):
    if current_nv in transition_map:
        for nv in transition_map[current_nv]:
            rows = df_sorted[(df_sorted["ov"] == current_nv) & (df_sorted["nv"] == nv)]
            for _, row in rows.iterrows():
                row_tuple = tuple(row)
                if row_tuple not in visited:
                    visited.add(row_tuple)
                    result_order.append(row)
                    dfs(nv)

# 先处理起始节点(ov=0)
start_rows = df_sorted[df_sorted["ov"] == 0]
for _, row in start_rows.iterrows():
    row_tuple = tuple(row)
    if row_tuple not in visited:
        visited.add(row_tuple)
        result_order.append(row)
        dfs(row["nv"])

# 处理剩余未访问的节点(比如自循环记录)
remaining_rows = df_sorted[~df_sorted.apply(tuple, axis=1).isin(visited)]
for _, row in remaining_rows.iterrows():
    result_order.append(row)

# 4. 生成带排序序号的结果
result_df = pd.DataFrame(result_order).reset_index(drop=True)
result_df["rn"] = result_df.index + 1

# 输出结果
print(result_df.to_string(index=False))

预期输出

id  nv  ov       date  rn
  1   1   0 01/02/2023   1
  1   2   1 01/02/2023   2
  1   3   2 01/02/2023   3
  1   1   3 01/02/2023   4
  1   4   1 01/02/2023   5
  1   5   4 01/03/2023   6
  1   6   5 01/03/2023   7
  1   7   6 01/04/2023   8
  1   7   7 01/04/2023   9

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:46:14