CiteSpace关键词合并实战指南:从数据清洗到可视化分析
背景痛点:一张图被“同义词”撕成碎片
做文献计量时,最尴尬的不是没数据,而是数据太“碎”。
CiteSpace .关键词网络里,同一概念被拆成好几簇:
- “machine learning” 与 “Machine Learning” 各成节点
- “COVID-19” 与 “covid19” 被当成两条独立记录
- “deep-learning” 与 “deep learning” 老死不相往来
结果:节点数虚高、中心性稀释、聚类标签一塌糊涂,图谱漂亮却没法讲故事。手工逐条合并?一千条能忍,一万条崩溃。本文给出一条 Python 自动化流水线,半小时把“碎片”拼成“整块”。
技术方案总览
- 读入原始关键词列 → pandas 统一格式
- 正则清洗大小写、标点、连字符
- 用词向量算语义距离,自动发现“长得像”的词
- 设定阈值,批量合并,写回 CSV
- 把清洗后的 CSV 重新喂给 CiteSpace,验证网络密度变化
完整代码:Jupyter Notebook 版
以下 cell 直接复制即可跑通,注释占比超 30%,新手可逐行对照。
# 0. 环境准备 # !pip install pandas gensim scikit-learn nltk -q import pandas as pd, re, json, itertools from collections import Counter from nltk.tokenize import word_tokenize from gensim.models import KeyedVectors # 1. 读入原始数据 # 假设从 CiteSpace export 出“关键词”列,存为 keywords_raw.csv df = pd.read_csv('keywords_raw.csv', encoding='utf-8-sig') kw_col = 'Keyword' # 列名按实际修改 # 2. 标准化函数:大小写、标点、空白 def normalize(text): text = text.lower() # 全小写 text = re.sub(r'[-–—]', ' ', text) # 连字符变空格,保留语义 text = re.sub(r'[^\w\s]', ' ', text) # 去标点 text = re.sub(r'\s+', ' ', text).strip() return text df['clean'] = df[kw_col].astype(str).apply(normalize) # 3. 生成词向量模型(英文维基预训练 50 维够用) # 下载:https://dl.fbaipublicfiles.com/fasttext/vectors-english/wiki-news-300d-1M.vec w2v_path = 'wiki-news-300d-1M.vec' w2v = KeyedVectors.load_word2vec_format(w2v_path, binary=False, limit=50000) def vec_mean(word_str): """把短语变向量:单词向量取平均""" tokens = word_tokenize(word_str) vecs = [w2v[t] for t in tokens if t in w2v] if not vecs: return None return sum(vecs) / len(vecs) # 4. 计算两两相似度,缓存加速 unique_kw = df['clean'].unique() vec_map = {w: vec_mean(w) for w in unique_kw if vec_mean(w) is not None} def cosine_sim(v1, v2): return dot(v1, v2) / (norm(v1) * norm(v2)) from numpy import dot, linalg.norm as norm sim_cache = {} for a, b in itertools.combinations(vec_map.keys(), 2): sim = cosine_sim(vec_map[a], vec_map[b]) if sim > 0.75: # 阈值先设 0.75,后面可调 sim_cache[frozenset([a, b])] = sim # 5. 合并算法:连通分量 import networkx as nx G = nx.Graph() for pair in sim_cache: G.add_edge(*pair, weight=sim_cache[pair]) components = list(nx.connected_components(G)) merge_map = {} for comp in components: canonical = min(comp, key=len) # 选最短词作为代表 for w in comp: merge_map[w] = canonical # 未命中合并的词保持不变 df['merged'] = df['clean'].map(merge_map).fillna(df['clean']) # 6. 保存结果 df.to_csv('keywords_merged.csv', index=False, encoding='utf-8-sig') print('合并前唯一词:', df['clean'].nunique()) print('合并后唯一词:', df['merged'].nunique())避坑指南
英文连字符
“pre-training” 与 “pretraining” 在语义上几乎等效,却常被当成两条。正则阶段把连字符统一替换成空格,可显著降低漏配率。但注意:某些领域缩写如 “COVID-19” 中的连字符是品牌符号,强行替换反而丢失信息,建议先白名单保护。领域专有名词
词向量对罕见词不友好,像 “qPCR” 这类实验缩写可能查不到向量。策略:先把高频专有词做成自定义词典,强制映射到标准写法,再跑相似度。相似度阈值
0.75 是经验起点,可画“阈值-压缩率”曲线:横轴阈值 0.6→0.9,纵轴唯一词下降比例,找拐点即可。阈值过低会把 “neural network” 与 “social network” 误合并;过高则漏掉 “SVM” 与 “support vector machine”。
验证:看网络密度怎么说
合并前后分别跑同一份数据,记录 CiteSpace 给出的 Network Density 与 Silhouette 值。通常密度会提高 15–40%,Silhouette 基本不变,说明聚类质量没牺牲。把两张图谱并排截图,肉眼可见“孤岛”消失,主聚类节点更大,颜色更集中,报告里放一张对比图,审稿人秒懂。
小结
关键词合并不是炫技,而是让 CiteSpace 真正“讲人话”的必经之路。把上面的 Notebook 跑通,你就能在半小时内把几千条 raw keywords 压成干净、统一、无歧义的词表,再回灌 CiteSpace,图谱瞬间从“满天星”变“主心骨”。下次遇到“同义词碎片”别再手工熬夜,让 Python 帮你一键拼好。