如何解读Quanteda计算的推特相似度结果并统计相似/相同推文?
咱们先拆解下你现在拿到的结果,再一步步教你怎么统计出实际的重复/相似推文数量:
一、先理解相似度数值的含义
你用table(tstat_sim@x)得到的两个数:
- 162743次相似度=1:这代表有162743对完全重复的推文。余弦相似度为1意味着两条推文的词向量完全一致,结合你之前的预处理(去掉短词、低频词、短推文),基本可以判定这些推文的核心内容完全相同(就算有标点、空格这类细微差异,经过dfm处理后也会被归一化成一致的向量)。
- 2288次相似度=0.9999:这是2288对高度相似的推文,它们的内容几乎一致,可能只有极细微的差别(比如多了个语气词、个别字符的差异,但核心语义和内容重合度极高)。
⚠️ 注意:textstat_simil返回的是无重复的无序文档对——比如只会统计(docA, docB)这一次,不会重复统计(docB, docA),也不会统计推文和自己的配对,所以不能直接把这些频次当成重复推文的总数哦!
二、统计实际的重复/相似推文数量
要得到真正有多少条推文属于重复或高度相似的范畴,我们需要把这些配对转换成独立的文档集合,避免重复计数:
1. 先把相似度结果转成数据框
sim_df <- as.data.frame(tstat_sim)
这个数据框会有三列:document1(第一个推文ID)、document2(第二个推文ID)、similarity(相似度值)。
2. 提取所有重复/相似的独立推文ID
- 提取所有有完全重复的推文ID:
duplicate_tweets <- unique(c(sim_df$document1[sim_df$similarity == 1], sim_df$document2[sim_df$similarity == 1])) # 查看完全重复的推文总数 length(duplicate_tweets)
这里的length(duplicate_tweets)就是所有至少有一条完全重复内容的推文数量(哪怕一条推文有10条重复,也只会被算一次)。
- 提取所有高度相似的推文ID:
similar_tweets <- unique(c(sim_df$document1[sim_df$similarity == 0.9999], sim_df$document2[sim_df$similarity == 0.9999])) # 查看高度相似的推文总数 length(similar_tweets)
- 如果要统计所有重复+高度相似的推文总数(去重后):
all_dup_similar <- unique(c(duplicate_tweets, similar_tweets)) length(all_dup_similar)
三、进阶:统计重复组的规模(可选)
如果你想知道这些重复推文是怎么分组的(比如是两两重复,还是有3条、4条一组的完全重复推文),可以用igraph包来做连通分量分析:
library(igraph) # 构建完全重复推文的关系图 dup_graph <- graph_from_data_frame(sim_df[sim_df$similarity == 1, c("document1", "document2")], directed = FALSE) # 找出所有连通分量(每个分量就是一组完全重复的推文) dup_clusters <- clusters(dup_graph) # 查看不同规模的重复组数量 table(dup_clusters$csize)
比如输出如果是2: 81371 3: 5,就代表有81371组是两两重复的推文,5组是3条完全一样的推文——n条推文的组会生成n*(n-1)/2个配对,这也能对应上你得到的相似度=1的频次总数。
四、关于你的预处理步骤的补充
你之前做的dfm_select(min_nchar = 2)、dfm_trim(min_termfreq = 10)、ntoken(dfmat_users) > 10这些操作,会过滤掉短词、低频词和短推文,这其实是合理的——因为这些内容对推文的核心语义影响很小,这样计算出来的相似度更能反映推文内容的真实重合度。
内容的提问来源于stack exchange,提问作者Shreya Agarwal

