如何将Pandas DataFrame中两列列表转换为包含重复键的字典列
解决Pandas中列表转字典时重复键的值收集问题
嘿,我太懂你的困扰了!你现在用dict(zip(*x))的核心问题在于——字典的键是唯一的,当同一个键多次出现时,后面的值会直接覆盖前面的,根本留不住所有对应的值。要实现把重复键的对应值收集成列表的需求,咱们换个思路构建字典就行。
方法一:使用collections.defaultdict(推荐,高效又好读)
咱们可以自定义一个处理函数,遍历每行的name和value配对,把每个值追加到对应键的列表里:
from collections import defaultdict def build_key_value_dict(row): # 初始化一个默认值为列表的字典,不用手动判断键是否存在 result_dict = defaultdict(list) # 遍历每一组name和value的配对 for name, val in zip(row['name'], row['value']): result_dict[name].append(val) # 转成普通字典(如果不需要defaultdict的特性的话) return dict(result_dict) # 把函数应用到DataFrame的每一行 self.data['dict'] = self.data.apply(build_key_value_dict, axis=1)
这个方法只需要遍历一次配对列表,效率很高,逻辑也直白,后续维护起来也省心。用你的示例测试的话,第一行的结果就是{'a': [1,4], 'b': [2], 'c': [3]},完全符合你的预期。
方法二:用字典推导式(简洁但效率稍低)
如果想写得更紧凑,也可以用字典推导式,不过这种方式对每个键都要重新遍历一遍配对列表,当列表很长时,效率会不如第一种方法:
self.data['dict'] = self.data.apply( lambda row: { key: [val for name, val in zip(row['name'], row['value']) if name == key] for key in set(row['name']) }, axis=1 )
为啥原来的代码不行?
你之前的dict(zip(*x))本质是把name和value按顺序配对后生成字典,但字典的键唯一性规则会导致:重复键的最后一次出现会覆盖之前所有对应的值。比如第一个示例里的a,最后一次对应的4会替换掉之前的1,所以最终字典里a的值只剩4。
内容的提问来源于stack exchange,提问作者Pedro Azevedo




