Python中无匹配列DataFrame计算后合并生成新DataFrame
正确实现基于文本余弦相似度的DataFrame合并方案
我看了你的需求和现有代码,发现几个关键问题:一是嵌套循环+反复append的方式不仅效率低下,还因为拼接逻辑错误,导致最终的DataFrame结构和你想要的横向合并不符;二是代码里的cos变量未初始化,会引发报错。下面给你一套清晰高效的解决方案:
第一步:补全文本向量与余弦相似度计算函数
首先我们需要明确文本转向量和余弦相似度的实现逻辑(你原代码里用到的text_to_vector和get_cosine函数),这里基于词频统计实现:
from collections import Counter import math import pandas as pd def text_to_vector(text): # 将文本按逗号分割为词,去除空格并转小写 words = [word.strip().lower() for word in text.split(',')] return Counter(words) def get_cosine(vec1, vec2): # 计算两个向量的余弦相似度 intersection = set(vec1.keys()) & set(vec2.keys()) numerator = sum([vec1[x] * vec2[x] for x in intersection]) sum1 = sum([vec1[x] ** 2 for x in list(vec1.keys())]) sum2 = sum([vec2[x] ** 2 for x in list(vec2.keys())]) denominator = math.sqrt(sum1) * math.sqrt(sum2) if not denominator: return 0.0 else: return float(numerator) / denominator
第二步:读取并预处理数据
读取你的示例DataFrame(如果是从CSV文件读取,替换成pd.read_csv()即可):
# 示例df1数据 df1 = pd.DataFrame({ 'Col1': [1, 2, 3], 'Col2': ['ABC', 'DEFn', 'GHI'], 'Col3': ["c, perl", "python, video", "web develpoment, java"] }) # 示例df2数据 df2 = pd.DataFrame({ 'ColA': [1, 2], 'ColB': ['X', 'Y'], 'ColC': ['Z', 'Z'], 'ColD': ["c, python", "perl, lakes"] })
第三步:生成所有配对并计算相似度
我们用**笛卡尔积(Cross Join)**生成df1和df2的所有行配对,然后批量计算余弦相似度,这比嵌套循环高效得多:
# 添加临时key实现笛卡尔积 df1['temp_key'] = 1 df2['temp_key'] = 1 # 合并得到所有行配对 cross_df = pd.merge(df1, df2, on='temp_key').drop('temp_key', axis=1) # 计算每一对的余弦相似度,生成VAL列 cross_df['VAL'] = cross_df.apply( lambda row: get_cosine(text_to_vector(row['Col3']), text_to_vector(row['ColD'])), axis=1 ) # 筛选VAL非零的行,得到最终结果df3 df3 = cross_df[cross_df['VAL'] != 0.0].reset_index(drop=True)
第四步:查看结果
运行print(df3)会得到符合你预期的输出:
Col1 Col2 Col3 ColA ColB ColC ColD VAL 0 1 ABC c, perl 1 X Z c, python 0.5 1 1 ABC c, perl 2 Y Z perl, lakes 0.5 2 2 DEFn python, video 1 X Z c, python 0.5
为什么这个方案更好?
- 效率更高:用pandas的向量化操作替代
iterrows()嵌套循环,避免了反复append导致的DataFrame重建开销,数据量大时优势明显。 - 逻辑清晰:从生成所有配对、计算相似度到筛选结果,每一步都明确可控,不易出错。
- 结构正确:直接横向合并df1和df2的列,符合你预期的输出格式,不会出现原代码里的行堆叠错误。
原代码的核心问题总结
- 拼接逻辑错误:原代码将df1和df2的行纵向堆叠(
append),而不是横向合并,导致结构不符合预期。 - 性能瓶颈:
iterrows()本身效率较低,加上循环内反复append,数据量大时会非常缓慢。 - 变量未初始化:代码中
cos['cosine_sim'] = cosine的cos变量未提前定义,会触发KeyError。
内容的提问来源于stack exchange,提问作者Shankar Pandey
相关产品推荐
相关产品推荐

