Networkx调用set_edge_attributes报expected 3 got 2解包错误
问题场景
为networkx.MultiDiGraph类型实例G设置边属性时,调用nx.set_edge_attributes方法触发ValueError,相关代码如下:
# a lib I wrote myself import dijkstra for edge in G.edges(): w = dijkstra.cost_cal(G, edge[0]) print(w, edge) # G: networkx.MultiDiGraph # edge: a tuple with two node IDs # w: float nx.set_edge_attributes(G, {edge: {"cost": w}})
运行时输出及报错信息:
0.05050505050505051 (1004215022, 1955253358) --------------------------------------------------------------------------- ValueError Traceback (most recent call last) Input In [6], in <cell line: 6>() 7 w = dijkstra.cost_cal(G, edge[0]) 8 print(w, edge) ----> 9 nx.set_edge_attributes(G, {edge: {"cost": w}}) File C:\ProgramData\Miniconda3\envs\PyGIS\lib\site-packages\networkx\classes\function.py:821, in set_edge_attributes(G, values, name) 818 else: 819 # `values` consists of doct-of-dict {edge: {attr: value}} shape 820 if G.is_multigraph(): ---> 821 for (u, v, key), d in values.items(): 822 try: 823 G[u][v][key].update(d) ValueError: not enough values to unpack (expected 3, got 2)
报错根因
MultiDiGraph属于多重图结构,允许同一对起止节点间存在多条平行边,因此边的唯一标识是(起点u, 终点v, 边键key)三元组。nx.set_edge_attributes处理多重图的字典格式入参时,会默认按三元组解包边标识,直接遍历G.edges()默认返回的是仅含两个节点ID的二元组,解包时长度不匹配触发错误。
解决方案
方案1:遍历边时携带key参数,构造符合要求的三元组传参
遍历边时传入keys=True参数,即可直接拿到包含边键的三元组,构造属性字典传入即可:import dijkstra for u, v, edge_key in G.edges(keys=True): w = dijkstra.cost_cal(G, u) nx.set_edge_attributes(G, {(u, v, edge_key): {"cost": w}})优化提示:可以先在循环中收集所有边的属性值,循环结束后一次性调用
nx.set_edge_attributes传入全量属性字典,减少重复函数调用的开销。方案2:直接定位边属性字典赋值,绕开格式校验
迭代到对应边后直接修改边的属性字典,不需要额外构造符合格式的传参字典,写法更简洁:import dijkstra for u, v, edge_key in G.edges(keys=True): w = dijkstra.cost_cal(G, u) # 直接给对应边的cost属性赋值 G[u][v][edge_key]["cost"] = w
注意:多重图场景下不要省略edge_key直接给边赋值,否则同一对节点间的所有平行边属性都会被覆盖,引发逻辑错误。
内容的提问来源于stack exchange,提问作者sroand
相关产品推荐
相关产品推荐

