如何合并Pandas DataFrame生成的嵌套字典中的重复值?
需求背景
要创建一个嵌套字典,用坐标字符串表示起点和终点,存储两者间的长度,参考格式如下:
graph = { 'a':{'b':10,'c':3}, 'b':{'c':1,'d':2}, 'c':{'b':4,'d':8,'e':2}, 'd':{'e':7}, 'e':{'d':9}}
输入数据(Excel读取的Pandas DataFrame内容)
Delta X Delta Y End X End Y Length Start X Start Y
6.7098 0.0000 26.5740 10.8226 6.7098 19.8642 10.8226
4.8364 0.0000 19.8642 10.8226 4.8364 15.0278 10.8226
0.0000 -6.6551 15.0278 10.8226 6.6551 15.0278 17.4777
11.5462 0.0000 26.5740 20.4308 11.5462 15.0278 20.4308
0.0000 2.9530 15.0278 20.4308 2.9530 15.0278 17.4777
0.0000 2.6396 26.5740 13.4622 2.6396 26.5740 10.8226
0.0000 2.9530 26.5740 20.4308 2.9530 26.5740 17.4777
11.5462 0.0000 26.5740 17.4777 11.5462 15.0278 17.4777
0.0000 4.0156 26.5740 17.4777 4.0156 26.5740 13.4622
6.7098 0.0000 26.5740 13.4622 6.7098 19.8642 13.4622
0.0000 2.6396 19.8642 13.4622 2.6396 19.8642 10.8226
期望输出格式
同一起点下的所有终点-长度条目需合并,例如:
'19.8642,10.8226' : {'26.5740,10.8226':6.7098, '19.8642,13.4622':2.6396}
当前问题
使用现有代码处理时,同一起点的第一条条目会被最新条目覆盖,当前输出:
{ '19.8642,10.8226': {'19.8642,13.4622': 2.6396}, '15.0278,10.8226': {'19.8642,10.8226': 4.8364}, '15.0278,17.4777': {'26.574,17.4777': 11.5462}, '15.0278,20.4308': {'26.574,20.4308': 11.5462}, '26.574,10.8226': {'26.574,13.4622': 2.6396}, '26.574,17.4777': {'26.574,20.4308': 2.953}, '26.574,13.4622': {'26.574,17.4777': 4.0156}, '19.8642,13.4622': {'26.574,13.4622': 6.7098} }
当前代码
fromto = df.iloc[:,:] df['end'] = df['End X'].astype(str) + ',' + df['End Y'].astype(str) df['start'] = df['Start X'].astype(str) + ',' + df['Start Y'].astype(str) fromto = fromto.set_index('start').T.to_dict('dict') fromto = dict(fromto) from2 = collections.defaultdict(dict) nodes_list = [] for i in fromto: fromto[i].pop('Delta X') fromto[i].pop('Delta Y') fromto[i].pop('End X') fromto[i].pop('End Y') fromto[i].pop('Start X') fromto[i].pop('Start Y') for start,v in fromto.items(): length = v['Length'] end = v['end'] from2[start][end] = length for i in v: nodes_list.append(start)
解决方案
问题出在fromto = fromto.set_index('start').T.to_dict('dict')这一步:当DataFrame中有重复的start值时,set_index会保留最后一条记录,直接覆盖之前的同起点条目。
修改思路:放弃转置转字典的方式,直接遍历每行数据,将起点、终点、长度逐步添加到嵌套字典中,确保同一起点的多条记录被累加而非覆盖。
优化后的代码:
import pandas as pd from collections import defaultdict # 假设df是已读取的Excel数据 df['end'] = df['End X'].astype(str) + ',' + df['End Y'].astype(str) df['start'] = df['Start X'].astype(str) + ',' + df['Start Y'].astype(str) graph = defaultdict(dict) nodes_list = [] # 遍历每行数据,逐个添加到嵌套字典 for _, row in df.iterrows(): start = row['start'] end = row['end'] length = row['Length'] graph[start][end] = length nodes_list.append(start) # 若需要转为普通字典而非defaultdict graph = dict(graph)
代码说明
- 使用
iterrows()遍历DataFrame每一行,确保每条记录都被处理 - 利用
defaultdict(dict)自动为新起点创建空字典,无需手动判断键是否存在 - 每行的终点和长度直接追加到对应起点的子字典中,不会覆盖已有条目
运行后,graph字典将包含所有同起点的终点-长度条目,比如'19.8642,10.8226'会同时包含'26.5740,10.8226':6.7098和'19.8642,13.4622':2.6396两个键值对。
内容的提问来源于stack exchange,提问作者Eduardo Jose Villasenor

