networkx 中为同一节点重复赋值节点属性(如 `g.nodes[node]["date"] = value`)会直接覆盖旧值;若数据文件中存在同一节点的多条日期记录,后读取的会覆盖先读取的,导致后续校验失败。
在使用 NetworkX 构建图并加载节点属性时,一个常见但易被忽略的陷阱是:节点属性不支持自动去重或合并,而是简单覆盖。您提供的代码中,node-dates.txt 文件存在对同一 nodeID 的多行记录(例如某节点出现两次,对应不同 date 值),而程序对每行都执行:
G.nodes[int(nodeID)]["date"] = line.split()[1]
这意味着:最后一次读取到该节点的 date 值将完全取代之前所有赋值。因此,当第二次遍历 node-dates.txt 进行断言校验时,若某节点在文件中首次出现的 date 已被后续同节点的另一条记录覆盖,则 assert(G.nodes[node]["date"] == original_date) 必然失败——这正是输出中 count_failed_assert = 2446 的根本原因。
✅ 正确做法是:显式处理重复节点。推荐以下两种策略:
仅保留首次出现的日期(默认优先):
if int(nodeID) not in G.nodes or "date" not in G.nodes[int(nodeID)]: G.nodes[int(nodeID)]["date"] = line.split()[1]
收集全部日期(如需多值):
date_val = line.split()[1]
if "date" not in G.nodes[int(nodeID)]:
G.nodes[int(nodeID)]["date"] = [date_val] # 初始化为列表
else:
G.nodes[int(nodeID)]["date"].append(date_val) # 追加而非覆盖⚠️ 注意事项:
总结:NetworkX 的节点属性是纯字典映射,无内置冲突解决机制。数据预处理阶段必须校验节点唯一性——推荐先用 pandas 或原生 Python 统计 node-dates.txt 中各节点出现频次(collections.Counter),再决定采用覆盖、保留首条或聚合策略,从根本上规避静默覆盖问题。