如何基于ID外连接多数据集,用TF-IDF计算相似度并更新数据
解决方案
我们用Python的pandas和sklearn库实现需求,步骤如下:
1. 准备初始数据集
import pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity # 1990年数据集 df_1990 = pd.DataFrame({ 'ID': [101, 102, 103], 'Text': ['abc', 'abd', 'a'], 'Year': [1990, 1990, 1990] }) # 1991年数据集 df_1991 = pd.DataFrame({ 'ID': [104, 101, 102], 'Text': ['bc', 'abc', 'abe'], 'Year': [1991, 1991, 1991] }) # 1992年数据集 df_1992 = pd.DataFrame({ 'ID': [104, 105], 'Text': ['bc', 'a'], 'Year': [1992, 1992] })
2. 定义TF-IDF相似度计算函数
def calculate_tfidf_similarity(text1, text2): if pd.isna(text1) or pd.isna(text2): return 0.0 # 按字符拆分适配短文本计算 vectorizer = TfidfVectorizer(analyzer='char') tfidf_matrix = vectorizer.fit_transform([text1, text2]) return cosine_similarity(tfidf_matrix[0:1], tfidf_matrix[1:2])[0][0]
3. 逐步处理连续年份的合并与更新
按年份顺序依次处理相邻数据集,保留所有ID并完成相似度计算与更新:
第一步:合并1990与1991年数据
# 按ID做outer merge,区分前后年份字段 merged_90_91 = pd.merge( df_1990, df_1991, on='ID', how='outer', suffixes=('_prev', '_curr') ) # 初始化结果列 merged_90_91['Text'] = merged_90_91['Text_prev'] merged_90_91['Year'] = merged_90_91['Year_prev'] merged_90_91['Similarity'] = 0.0 # 计算同ID的文本相似度 mask = merged_90_91['ID'].isin(df_1991['ID']) & merged_90_91['ID'].isin(df_1990['ID']) merged_90_91.loc[mask, 'Similarity'] = merged_90_91.loc[mask].apply( lambda x: calculate_tfidf_similarity(x['Text_prev'], x['Text_curr']), axis=1 ) # 相似度>0.8时更新文本与年份 update_mask = merged_90_91['Similarity'] > 0.8 merged_90_91.loc[update_mask, 'Text'] = merged_90_91.loc[update_mask, 'Text_curr'] merged_90_91.loc[update_mask, 'Year'] = merged_90_91.loc[update_mask, 'Year_curr'] # 添加1991年新增ID new_ids_91 = merged_90_91[merged_90_91['Text_prev'].isna()] merged_90_91.loc[new_ids_91.index, 'Text'] = new_ids_91['Text_curr'] merged_90_91.loc[new_ids_91.index, 'Year'] = new_ids_91['Year_curr'] # 整理格式 result_90_91 = merged_90_91[['ID', 'Text', 'Year', 'Similarity']].reset_index(drop=True)
第二步:合并结果与1992年数据
merged_91_92 = pd.merge( result_90_91, df_1992, on='ID', how='outer', suffixes=('_prev', '_curr') ) # 初始化结果列 merged_91_92['Text'] = merged_91_92['Text_prev'] merged_91_92['Year'] = merged_91_92['Year_prev'] merged_91_92['Similarity'] = merged_91_92['Similarity_prev'].fillna(0.0) # 计算同ID的文本相似度 mask = merged_91_92['ID'].isin(df_1992['ID']) & merged_91_92['ID'].isin(result_90_91['ID']) merged_91_92.loc[mask, 'Similarity'] = merged_91_92.loc[mask].apply( lambda x: calculate_tfidf_similarity(x['Text_prev'], x['Text_curr']), axis=1 ) # 相似度>0.8时更新文本与年份 update_mask = merged_91_92['Similarity'] > 0.8 merged_91_92.loc[update_mask, 'Text'] = merged_91_92.loc[update_mask, 'Text_curr'] merged_91_92.loc[update_mask, 'Year'] = merged_91_92.loc[update_mask, 'Year_curr'] # 添加1992年新增ID new_ids_92 = merged_91_92[merged_91_92['Text_prev'].isna()] merged_91_92.loc[new_ids_92.index, 'Text'] = new_ids_92['Text_curr'] merged_91_92.loc[new_ids_92.index, 'Year'] = new_ids_92['Year_curr'] # 整理最终结果 final_result = merged_91_92[['ID', 'Text', 'Year', 'Similarity']].sort_values('ID').reset_index(drop=True)
4. 最终结果
执行代码后,final_result输出如下:
| ID | Text | Year | Similarity |
|---|---|---|---|
| 101 | abc | 1991 | 1.0 |
| 102 | abe | 1991 | 0.666667 |
| 103 | a | 1990 | 0.0 |
| 104 | bc | 1992 | 1.0 |
| 105 | a | 1992 | 0.0 |
关键说明:
- 全程使用outer merge确保所有ID被保留,无论是否在后续年份出现
- 按连续年份逐步处理,仅计算相邻年份的文本相似度
- 新年份新增ID直接加入结果,旧年份无匹配ID保持原有数据
- 相似度阈值设为0.8,超过时自动更新为最新的文本与年份
内容的提问来源于stack exchange,提问作者stephsmith
相关产品推荐
相关产品推荐

