如何删除语料库中的相似文档?余弦相似度去重方案求助
解决重复文档删除问题:从余弦相似度到保留唯一文档
我懂你现在的困境:已经用余弦相似度找出了那些只有页眉页脚差异的重复新闻,但嵌套循环删除的方法总是出问题。其实不用纠结复杂的循环,我们可以用更高效的方式来分组并保留唯一文档。
先确认你的前期处理是对的
首先,你之前生成余弦相似度矩阵并转换为二值矩阵的代码没问题,先贴出来确认:
# 构建文档特征矩阵 myDfm <- dfm(as.character(docs$text_main), verbose=FALSE) # 计算文档间余弦相似度 cosinesim <- textstat_simil(x=myDfm, selection=docnames(myDfm), margin="documents", method="cosine") cosinemat <- as.matrix(cosinesim) # 处理矩阵:对角线设为0,按阈值转换为二值矩阵 diag(cosinemat) <- 0 cosinemat[cosinemat >= 0.9] <- 1 cosinemat[cosinemat < 0.9] <- 0
方案1:用连通分量分组(推荐,高效处理多重复文档)
这种方法把相似文档看作图中的节点,相似的节点连在一起,然后把每个连通的节点组视为重复集合,每组只留一个文档。我们可以用igraph包来实现:
# 安装并加载igraph(如果没装的话) if (!require(igraph)) { install.packages("igraph") library(igraph) } # 把二值相似度矩阵转换成无向图 g <- graph_from_adjacency_matrix(cosinemat, mode = "undirected", weighted = NULL) # 获取每个文档所属的分组ID doc_groups <- components(g)$membership # 每组只保留第一个出现的文档,得到唯一文档集合 unique_docs <- docs[!duplicated(doc_groups), ]
这个方法的优势是不管一组里有多少个重复文档,都能一次性处理,不会出现循环中修改数据框导致的索引混乱问题。
方案2:基础R标记法(不用额外包)
如果你不想装新包,可以用标记法:先标记要保留的文档,最后再筛选,避免循环中修改原数据框:
# 初始化保留标记,默认全部保留 keep <- rep(TRUE, nrow(docs)) # 遍历每个文档 for (i in 1:nrow(cosinemat)) { if (!keep[i]) next # 如果已经标记为删除,直接跳过 # 找到所有和当前文档相似的文档 duplicate_indices <- which(cosinemat[i, ] == 1) # 把这些重复项标记为不保留,只保留当前文档 keep[duplicate_indices] <- FALSE keep[i] <- TRUE } # 筛选出保留的文档 unique_docs <- docs[keep, ]
额外优化:预处理去掉页眉页脚
其实你可以先预处理去掉页眉页脚,这样余弦相似度的计算会更准确,避免页眉的干扰:
# 用正则表达式去掉开头到"Body"的页眉部分,只留正文 docs$text_clean <- gsub("^.*Body", "", docs$text_main) # 用清理后的正文构建dfm,再计算相似度 myDfm <- dfm(as.character(docs$text_clean), verbose=FALSE)
这样处理后,相似度的计算会更聚焦于正文内容,阈值设置也会更精准。
内容的提问来源于stack exchange,提问作者lispang
相关产品推荐
相关产品推荐

