如何用 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 日期类型。
备注:内容仅供参考。
