如何从两个字典中提取共同键的键值对并计算对应值的余弦相似度
解决字典提取与余弦相似度计算问题
这个问题我之前也琢磨过,给你一步步拆解清楚~
一、生成共有键的新字典dict3
其实不用绕复杂的循环嵌套,用字典推导式一行就能搞定,既简洁又高效:
dict1 = {'A':'3','B':'6','E':'9'} dict2 = {'A':'4','B':'8','C':'12','D':'16','E':'20'} # 提取dict2中与dict1共有的键值对 dict3 = {k: v for k, v in dict2.items() if k in dict1} print(dict3) # 输出: {'A':'4','B':'8','E':'20'}
如果一定要用循环实现,可能你之前的循环逻辑没处理对,正确的写法是先初始化空字典,然后遍历dict2的键值对,判断键是否在dict1中,符合条件就添加到dict3:
dict3 = {} for key, value in dict2.items(): if key in dict1: dict3[key] = value
另外还有一种思路:既然dict1的键都是我们需要的,也可以直接遍历dict1的键,从dict2中取值(前提是dict2包含所有dict1的键,你的例子里刚好满足这个条件):
dict3 = {k: dict2[k] for k in dict1}
二、计算dict1与dict3的余弦相似度
余弦相似度是专门针对向量计算的,所以必须先把字典里的字符串数值转换成有序的数值向量才行。具体步骤如下:
1. 转换为数值向量
首先把两个字典的值提取出来,转成整数/浮点数列表,要保证两个向量的元素顺序对应(Python 3.7+字典是插入有序的,直接取values()没问题;如果担心顺序不一致,也可以按排序后的键来提取):
# 直接按字典顺序提取转换 vec1 = [int(val) for val in dict1.values()] vec3 = [int(val) for val in dict3.values()] # 或者按排序后的键提取,确保顺序绝对一致(更稳妥) sorted_keys = sorted(dict1.keys()) vec1 = [int(dict1[k]) for k in sorted_keys] vec3 = [int(dict3[k]) for k in sorted_keys]
2. 计算余弦相似度
可以手动实现公式,也可以用numpy库简化计算:
方法一:手动计算
import math # 计算向量点积 dot_product = sum(a * b for a, b in zip(vec1, vec3)) # 计算两个向量的模长 magnitude1 = math.sqrt(sum(x**2 for x in vec1)) magnitude3 = math.sqrt(sum(x**2 for x in vec3)) # 计算余弦相似度 cosine_similarity = dot_product / (magnitude1 * magnitude3) print(cosine_similarity) # 你的例子中结果约为0.997
方法二:用numpy简化
如果你经常做数值计算,用numpy会更省心:
import numpy as np vec1_np = np.array(vec1) vec3_np = np.array(vec3) cosine_similarity = np.dot(vec1_np, vec3_np) / (np.linalg.norm(vec1_np) * np.linalg.norm(vec3_np)) print(cosine_similarity) # 和手动计算结果完全一致
这里要划重点:不能直接用字典计算余弦相似度,因为字典是键值对的集合,没有向量的有序性和数值运算能力,必须先转换成对应的数值向量才行。
内容的提问来源于stack exchange,提问作者Beyonder09
相关产品推荐
相关产品推荐

