PAYATHON 2026

如何用 pandas 自动追溯多段商品变更关系?

数据小陈

结论

可以把每条记录理解为一次“前序商品 → 新商品”的变更,并用 (store, new_item) 建立查找表。先找出没有被其他记录引用为 previous_item 的末端商品,再沿着前序记录逐条回溯,直到找不到更早的记录。

下面的实现依赖题目给出的条件:同一门店内 new_item 唯一。示例中的 change_date 为 YYYY-MM 格式;代码根据商品关系追溯,不按日期排序来确定关联顺序。

pandas 实现

import pandas as pd

# 若 df_table_one 尚未创建,可用题目中的数据创建 DataFrame。
records = df_table_one.to_dict("records")

# 根据门店和 new_item 定位对应的变更记录。
by_new_item = {
    (row["store"], row["new_item"]): row
    for row in records
}

# 被后续记录引用为 previous_item 的商品,不是链条末端。
referenced_items = set(
    zip(df_table_one["store"], df_table_one["previous_item"])
)

# 末端记录代表每条链的最新商品。
latest_rows = [
    row for row in records
    if (row["store"], row["new_item"]) not in referenced_items
]

results = []

for latest in latest_rows:
    current = latest
    visited = set()

    while True:
        key = (current["store"], current["new_item"])

        # 防止数据中存在循环关系时陷入无限循环。
        if key in visited:
            raise ValueError(f"检测到循环变更关系:{key}")
        visited.add(key)

        previous_key = (current["store"], current["previous_item"])
        previous_row = by_new_item.get(previous_key)

        if previous_row is None:
            # current 是链条中最早的一条记录。
            break

        current = previous_row

    results.append({
        "store": latest["store"],
        "latest_item": latest["new_item"],
        "latest_change_date": latest["change_date"],
        "first_item": current["previous_item"],
        "first_change_date": current["change_date"],
    })

result_df = pd.DataFrame(results)
print(result_df)

根据题目中的数据,结果如下:

  store latest_item latest_change_date   first_item first_change_date
0     A     red car            2025-01    green car           2025-01
1     B    red boat            2025-01   green boat           2025-01
2     C   red plane            2025-01  yellow plane           2024-01
3     C    red bike            2025-01    green bike           2025-01

实现要点

  • by_new_item 使用 (store, new_item) 作为键,避免不同门店的同名商品被匹配到一起。
  • latest_rows 找出各条链的末端:这些记录的 new_item 没有出现在同一门店的 previous_item 中。
  • 每轮循环都将当前记录的 previous_item 作为下一条记录的 new_item 查找。找不到匹配记录时,当前记录的 previous_item 就是链条起点。

如果同一门店内可能有重复的 new_item,查找关系就不唯一,不能直接用这个字典确定前序记录;需要先明确重复项的处理方式。如果 change_date 的格式不能直接按年月识别,且还需要按日期筛选或排序,应先将其转换为 pandas 日期类型。

备注:内容仅供参考。