共现矩阵 + 网络关系图:3 步把 10 万条评论里的”隐藏关系”挖出来 老板们最常问:“差评”和”客服”是同一拨人说的吗?”物流”和”退货”哪个先出现?
答案就在共现关系 里——两个词在同一段文本 里同时出现的频次。我们的 共现矩阵和网络关系图生成软件 把这事儿做成了一键式:导入 TXT → 出 Excel 矩阵 + 网络图。
下面拆解原理和实战代码。
一、什么是共现?为什么要做? 共现(co-occurrence) :两个词在同一窗口(句子/段落/文档)里同时出现。
业务价值 :
找出”售后问题”的子话题(差评+客服+退货+退款 共现频繁 → 是个完整议题)
发现品牌关联(小米+华为+苹果 经常一起被对比)
找热点话题(疫情+口罩+核酸 共现 = 疫情相关)
二、3 步法实战 第 1 步:分词 + 关键词提取 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import jiebaimport jieba.analysejieba.load_userdict('custom_words.txt' ) with open ('comments.txt' , encoding='utf-8' ) as f: raw_lines = [line.strip() for line in f if line.strip()] per_line_keywords = [] for line in raw_lines: keywords = jieba.analyse.textrank(line, topK=10 , withWeight=False ) per_line_keywords.append(keywords) print (per_line_keywords[0 ])
两种策略 :
全分词 :保留所有词,矩阵大但全
关键词提取 (TextRank/TF-IDF):保留 Top 10,矩阵紧凑、噪声少
建议用关键词提取 ——全分词会把”很/不/是”这种停用词拉进矩阵,污染结果。
第 2 步:滑窗统计共现次数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 from itertools import combinationsfrom collections import defaultdictimport numpy as npall_keywords = [w for line in per_line_keywords for w in line] from collections import Counterkeyword_freq = Counter(all_keywords) top_keywords = [w for w, c in keyword_freq.most_common(50 )] K = len (top_keywords) co_matrix = np.zeros((K, K), dtype=int ) word_to_idx = {w: i for i, w in enumerate (top_keywords)} for line_keywords in per_line_keywords: present = [w for w in line_keywords if w in word_to_idx] for w1, w2 in combinations(set (present), 2 ): i, j = word_to_idx[w1], word_to_idx[w2] co_matrix[i][j] += 1 co_matrix[j][i] += 1 import pandas as pddf_matrix = pd.DataFrame(co_matrix, index=top_keywords, columns=top_keywords) df_matrix.to_excel('cooccurrence_matrix.xlsx' )
关键点 :
combinations(set(present), 2):同一条评论里任意两个 关键词都算共现,不管顺序、不管距离
共现次数 = 两个词在多少条评论里同时 出现过
矩阵是对称的 ——A-B 共现 = B-A 共现
第 3 步:画网络关系图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import networkx as nximport matplotlib.pyplot as pltG = nx.Graph() threshold = 5 for i in range (K): for j in range (i+1 , K): if co_matrix[i][j] >= threshold: w1, w2 = top_keywords[i], top_keywords[j] G.add_edge(w1, w2, weight=int (co_matrix[i][j])) for word in G.nodes(): G.nodes[word]['freq' ] = keyword_freq[word] pos = nx.spring_layout(G, k=0.5 , iterations=50 , seed=42 ) fig, ax = plt.subplots(figsize=(14 , 10 )) node_sizes = [G.nodes[n]['freq' ] * 20 for n in G.nodes()] edge_widths = [G[u][v]['weight' ] / 5 for u, v in G.edges()] nx.draw_networkx_nodes(G, pos, node_size=node_sizes, node_color='#6e5cff' , alpha=0.85 , ax=ax) nx.draw_networkx_edges(G, pos, width=edge_widths, edge_color='rgba(0, 212, 255, 0.4)' , ax=ax) nx.draw_networkx_labels(G, pos, font_size=10 , font_color='#fff' , font_family='sans-serif' , ax=ax) edge_labels = {(u, v): G[u][v]['weight' ] for u, v in G.edges() if G[u][v]['weight' ] >= 20 } nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=8 , ax=ax) ax.set_title('关键词共现网络图(共现 ≥ 5 次)' , fontsize=15 ) ax.axis('off' ) plt.tight_layout() plt.savefig('cooccurrence_network.png' , dpi=150 , bbox_inches='tight' )
三、共现矩阵的”边”该怎么用? 过滤阈值 非常关键:
threshold
效果
1
几乎所有词都连,画面像毛线球
5
保留主要关系,适合初次探索
20
只保留强关联,适合”找核心议题”
50
只剩 5-10 个 hub 节点,适合精修
踩坑 :threshold 一刀切可能漏掉”中频但重要”的关系。建议多画几张 (5/20/50 各一张),对比着看。
四、进阶:社区发现 共现网络图里团在一起 的词,往往是同一议题 。可以用社区发现算法自动识别:
1 2 3 4 5 6 7 8 9 10 from networkx.algorithms.community import greedy_modularity_communitiescommunities = greedy_modularity_communities(G, resolution=1.0 ) print (f'识别出 {len (communities)} 个社区' )for i, comm in enumerate (communities, 1 ): print (f'社区 {i} ({len (comm)} 词): {", " .join(sorted (comm, key=lambda w: -G.nodes[w]["freq" ])[:5 ])} ' )
业务解读 :
社区 1 = 物流相关
社区 2 = 客服相关
社区 3 = 电池续航相关
这是老板们最爱的产出 ——不用自己读 10 万条评论,3 个社区就把”用户在抱怨什么”拎出来了。
有些词连接多个社区 ——比如”质量”既跟”做工”近、也跟”客服”近、也跟”物流”近。这样的”枢纽词”用 PageRank 算:
1 2 3 4 5 6 7 8 9 pr = nx.pagerank(G, weight='weight' ) hub_words = sorted (pr.items(), key=lambda x: -x[1 ])[:10 ] print ('枢纽词 Top 10:' )for word, score in hub_words: print (f' {word} : {score:.4 f} ' )
枢纽词 就是”产品总抓手”——提升这词相关的体验,能带动多个社区。
六、共现 vs LDA:什么时候用哪个?
维度
共现矩阵
LDA 主题
输出形式
词-词关系网
文档-主题分布
算法
简单统计
概率图模型
训练时间
几秒
几分钟-几小时
适合
探索性分析、找关系
主题抽取、文档归类
输出解读难度
直观(看图)
较抽象(看 Top 词)
业务建议 :先用共现矩阵快速摸底,再用 LDA 做精细主题分析。
七、踩坑大全 1. 共现窗口大小 :默认”同一行评论”= 1 个窗口。也可以”同一段”= 滑窗 size=5(前后各 5 个词)。窗口越大,关系越宽泛但矩阵越密。
2. 中文分词 :自定义词典不加,”小米/手机”被切散,”小米”和”手机”的共现次数会异常高 (因为每个含”小米手机”的句子都被算作”小米+手机”共现)。
3. 停用词 :必须砍!否则”的/了/是”会和所有词共现,矩阵被噪声淹没。
4. 节点标签颜色 :黑底深色主题下,黑色标签会消失。要么用浅色标签,要么节点加白边。
5. 节点重叠 :spring_layout 对密集图 会节点重叠。解决:换 nx.kamada_kawai_layout(G) 或增加 k 参数(节点间距)。
6. 大图导出 :100+ 节点 + DPI 300 会卡 5 分钟。建议输出 SVG 矢量格式,CDR 可以直接打开。
八、典型业务应用
电商评论分析 :发现”差评主题分布”和”差评关键词关系”
学术论文分析 :找出某领域的研究热点词和子方向
舆情监控 :突发事件中关键人物/事件/地点的关系网
用户调研 :NPS 调研中”高分原因”和”低分原因”的关系
我们的 共现矩阵和网络关系图生成软件 把上面所有步骤封装成可视化界面:导入 TXT → 自动分词 → 自动统计共现 → 一键出 Excel 矩阵 + 矢量网络图(SVG 格式,CDR 可直接编辑)。支持自定义关键词库、停用词库、阈值滑块 ——业务人员不用写代码也能挖出文本里的隐藏关系。