简介:Python 词云完整教程 PDF 面向文本挖掘与数据可视化初学者及中级用户,围绕 wordcloud 与 matplotlib 两库,系统讲解从文本预处理、权重计算到词云生成、展示与保存的完整流程,并给出 PyCharm、Python 3.7 及对应库版本的环境配置参考。内容以7个递进案例展开,既包含最简调用,也覆盖中文不分词、中文分词、蒙版形状、自定义配色以及按关键词和权重定制词云等进阶用法,可服务于项目报告、数据分析、社交媒体监控与教学演示等场景。资源包共1个PDF文件,大小约2.07MB,单文件便于通读与按案例检索,代码示例和运行结果可辅助对照练习。已有109人学习,适合希望快速掌握词云制作思路并积累可视化实践的读者。
1. 从一份纯文本到一张能进报告的图:这套词云方案先解决什么
做文本分析类课设的人,常常卡在同一个地方:词频统计跑完了,结论也有了,最后要放进报告,手里却只有一张 Excel 截图或者一段控制台输出。评审要的是“扫一眼就知道这批文本在讲什么”的图,不是一串数字。这套 Python 词云方案处理的正是最后这一步:拿一份纯文本进去,从最简的一次调用开始,依次叠加中文分词、蒙版形状、蒙版取色、自定义颜色函数,最后落到按关键词权重生成。七个案例层层递进,每一层只增加一个变量,出问题能立刻定位到是哪一层引入的。它适合正在做文本挖掘、舆情观察、课程报告的在校生,也适合需要把分析结论放进汇报材料的从业者。整套流程只依赖 wordcloud、matplotlib、jieba 三个库,环境是 Python 3.7 + wordcloud 1.9.3 + matplotlib 3.5.3,换一份文本、改几个参数就能直接跑自己的数据。
2. 环境与工程骨架:Python 3.7 + wordcloud 1.9.3 的最小可运行结构
2.1 依赖清单与版本约束
词云这条链路上的库不算多,但每个位置都有明确分工,少一个环节就出不了图。先把它们列清楚,后面看代码时才知道每一行在跟谁打交道。
| 库 | 版本 | 在流程里负责什么 |
|---|---|---|
| wordcloud | 1.9.3 | 词汇排布、按权重决定字号、生成图像对象 |
| matplotlib | 3.5.3 | 显示画布、关闭坐标轴、交互式预览 |
| jieba | 用当前稳定版即可 | 中文分词,以及后面案例 07 的关键词权重抽取 |
| Pillow | 随 wordcloud 一起装上 | 读取蒙版图片、把像素转成数组 |
| numpy | 随 matplotlib 一起装上 | 把图片转成 mask 需要的 ndarray |
安装命令按教程给的版本号固定下来,这一步不要图省事直接pip install wordcloud。原因很简单:wordcloud 在 1.x 早期版本和 1.9.x 之间对mask、background_color=None的处理细节有差异,而网上能搜到的绝大部分报错帖写的又不是同一个版本,版本一漂,你照着帖子改反而越改越乱。
# 三个核心库,版本按教程固定,避免接口行为漂移 pip install wordcloud==1.9.3 pip install matplotlib==3.5.3 pip install jieba # 装完自检,确认版本和教程一致再往下走 python -c "import wordcloud, matplotlib; print(wordcloud.__version__, matplotlib.__version__)"这里有一个大多数人都会遇到的麻烦:wordcloud 带 C 扩展,在 Windows 上如果没匹配到现成的 wheel 包,pip 会退回去做源码编译,然后报一串Microsoft Visual C++ 14.0 is required。遇到这种情况不要装编译器,先确认 Python 是 3.7 的 64 位版本,再升级 pip 让它能拉到对应的 wheel;实在拉不到,就退到 32 位 Python 或者换一个 prebuilt wheel 装。这一步解决不了,后面七个案例一行都跑不起来。
2.2 目录结构与七个案例的分层
七个案例如果全塞进一个.py文件,变量名会互相污染,改一个地方要重新确认另外六段还对不对,调试体验很差。我一般按“一个案例一个入口文件”来摆,把读文本、分词、字体路径这三件重复出现的活抽到common.py里。
wordcloud_demo/ ├── data/ │ ├── sample.txt # 无分词场景的纯文本 │ └── book.txt # 中文长文本,utf-8 编码 ├── fonts/ │ └── cn_font.ttf # 中文字体,ttf 或 otf 都可以 ├── masks/ │ ├── black_mask.png # 纯形状蒙版,黑白二值 │ └── color_mask.png # 带颜色的蒙版,用于取色 ├── outputs/ # 生成的 png 统一落这里 ├── common.py # 读文本、分词、字体路径 ├── case01_minimal.py ├── case02_cn_nocut.py ├── case03_cn_cut.py ├── case04_mask.py ├── case05_mask_color.py ├── case06_color_func.py └── case07_tfidf.py这么分层的好处是每个案例只改一件事:案例 02 只换字体和画布参数,案例 03 只插入分词,案例 04 只加 mask。跑出来效果不对时,把上一个案例再跑一次,两边一对比,问题范围立刻被限制在新增的那几行里。这也是整套方案能当“模板”复用的关键——你以后接了新数据,只需要动data/和common.py,七个入口文件基本不用改。
2.3 文本入口与字体路径的统一约定
词云代码里最常见的柔性问题,其实是路径和编码:脚本在 PyCharm 里点运行能出图,换到命令行python case03_cn_cut.py就报FileNotFoundError,因为相对路径是跟着当前工作目录走的。把路径统一在common.py里基于脚本自身位置拼出来,这一类问题就一次性消掉了。
# common.py import os import jieba # 以 common.py 所在目录为基准,避免工作目录不同导致的找不到文件 BASE = os.path.dirname(os.path.abspath(__file__)) def read_text(rel_path, encoding='utf-8'): """按 utf-8 读文本;遇到 gbk 文本时把 encoding 换成 'gbk' 再调一次""" path = os.path.join(BASE, rel_path) with open(path, 'r', encoding=encoding) as f: return f.read() def cut(text, stop_words=None): """jieba 精确模式分词,过滤单字和停用词后拼回空格分隔的字符串""" tokens = [] for w in jieba.cut(text): w = w.strip() if len(w) < 2: # 单字多数是虚词,先丢掉 continue if stop_words and w in stop_words: continue tokens.append(w) return ' '.join(tokens) # 字体路径同样基于脚本位置,Windows 可换成 C:/Windows/Fonts/simhei.ttf 的绝对路径 FONT = os.path.join(BASE, 'fonts', 'cn_font.ttf')read_text里显式写encoding='utf-8'不是可选动作。中文文本在 Windows 上默认按 GBK 解码,遇到 utf-8 内容会抛UnicodeDecodeError,而报错行号往往落在f.read()上,看起来像文件坏了,其实只是编码没对上。cut里过滤掉长度为 1 的词,是因为中文分词结果里“的、了、是、在”这类单字占比很高,不滤掉它们会占满画布上最好的位置。停用词表我一般单独放一个stopwords.txt,按行读取成 set 传进来,官方库自带的停用词只对英文有效,中文这块必须自己补。
提示:字体文件不要用系统里随便找一个的 ttf,优先选字重完整的中文字体。缺字的字体不会报错,只会在画布上留下一排方块,排查起来很绕。
3. 七个案例的递进设计:从三行调用到权重驱动
3.1 案例 01-02:先跑通默认调用,再解决中文直出
案例 01 的作用不是出效果图,而是验证环境。它把所有可调项都用默认值,只要这张图能出来,就说明 wordcloud 和 matplotlib 装对了、文本能读到、画布能渲染,后面所有问题都可以排除掉环境因素。
# case01_minimal.py # -*- coding: utf-8 -*- from wordcloud import WordCloud import matplotlib.pyplot as plt from common import read_text # 读入文本,默认英文/无空格分隔场景 text = read_text('data/sample.txt') # 全部用默认参数:画布 400x200,白色背景,按空格切词 wc = WordCloud().generate(text) # 显示:bilinear 让缩放更平滑,axis off 去掉坐标轴 plt.imshow(wc, interpolation='bilinear') plt.axis('off') plt.show() # 落盘,后续所有案例都统一输出到 outputs/ wc.to_file('outputs/case01.png')generate(text)内部做了三件事:按空格切词、统计词频、按词频分配字号并把词排进画布。默认画布只有 400x200,词一多就会显得挤,interpolation='bilinear'解决的是显示时的插值锯齿,跟导出图片的清晰度无关,这一点很多人会混淆。
案例 02 把中文文本直接丢进去,只增加三个参数:font_path指定中文字体、width/height把画布放大到 800x600、mode='RGBA'加background_color=None得到透明背景。
# case02_cn_nocut.py from wordcloud import WordCloud import matplotlib.pyplot as plt from common import read_text, FONT text = read_text('data/book.txt') wc = WordCloud( font_path=FONT, # 中文字体,缺了它整张图都是方块 width=800, height=600, # 画布放大,避免词挤成一团 mode='RGBA', # 带透明通道 background_color=None, # 背景透明,方便贴到 PPT 或海报上 ).generate(text)这个案例故意不做分词,是为了让你亲眼看到不分词的后果:整段中文因为中间没有空格,会被 WordCloud 当成一个超长“单词”,画布上只出现几个巨大的词块,或者干脆一片空白。这个“错误示范”很有价值,它把分词的必需性从一句结论变成了你亲眼见过的现象,后面答辩被问到“为什么要用 jieba”时,这就是最好的回答素材。
3.2 案例 03:jieba 分词接入,把长句拆成可统计的词
中文没有空格分隔,WordCloud 拿到的必须是用空格隔开的词序列,中间这一层就由 jieba 补上。改动只有一行,但它是整条链路的分水岭。
# case03_cn_cut.py from wordcloud import WordCloud import matplotlib.pyplot as plt import jieba from common import read_text, FONT text = read_text('data/book.txt') # 精确模式切词,再用空格拼回去交给 WordCloud text = ' '.join(jieba.cut(text)) print(text[:100]) # 打印前 100 字符,肉眼确认切得对不对 wc = WordCloud( font_path=FONT, width=800, height=600, mode='RGBA', background_color=None, ).generate(text) plt.imshow(wc, interpolation='bilinear') plt.axis('off') plt.show() wc.to_file('outputs/case03.png')jieba.cut(text)返回的是生成器,不是列表,所以必须用' '.join()消费掉再传给 WordCloud;直接传生成器进去会触发类型错误。jieba.cut默认是精确模式,另有全模式和搜索引擎模式:全模式把句子里所有可能成词的部分都切出来,速度快但歧义多,词云上会冒出大量碎片词;搜索引擎模式在精确模式基础上对长词再切一次,召回率更高。词云场景我一般只用精确模式,因为画布空间有限,宁可少几个词,也不要一堆切碎的半截词把版面撑乱。
打印前 100 个字符这一步别省。分词切错(比如人名被拆成两个字、专业术语被拦腰截断)在图上不一定看得出来,但在文本层面一眼就能发现。真遇到专有名词被切碎,jieba.load_userdict('dict.txt')加载一份自定义词典,一行一个词,效果立竿见影。
3.3 案例 04-05:蒙版形状与蒙版取色,把方图变成图形
默认词云永远是矩形,放进设计稿里很突兀。案例 04 用 mask 把词的排布限制在一个形状内,案例 05 再让词的颜色从一张彩色图上取,两步合起来就是“形状 + 配色”都跟着素材走。
# case04_mask.py from wordcloud import WordCloud from PIL import Image import numpy as np import matplotlib.pyplot as plt import jieba from common import read_text, FONT text = ' '.join(jieba.cut(read_text('data/book.txt'))) # 蒙版必须是 ndarray,形状决定词的落点分布 mask = np.array(Image.open('masks/black_mask.png')) wc = WordCloud( mask=mask, # 传了 mask 后,width/height 会被忽略 font_path=FONT, mode='RGBA', background_color=None, ).generate(text) plt.imshow(wc, interpolation='bilinear') plt.axis('off') plt.show() wc.to_file('outputs/case04.png')关键点在 mask 的像素语义:WordCloud 把 mask 里接近白色(255)的区域当作不绘制区,非白区域才是词的落点。所以做蒙版图时,想要出词的地方涂黑、不要的地方留白,这跟多数人凭直觉画的“白色是主体”正好相反,也是后面避坑章节要重点讲的一条。另外,一旦传了mask,代码里再写width=800是不会生效的,画布尺寸直接由蒙版图片的像素尺寸决定,蒙版太大(比如 4000px 宽)会让排布慢到几十秒。
案例 05 在案例 04 基础上多一个取色步骤:ImageColorGenerator读取蒙版的颜色分布,recolor把词的颜色替换成对应位置的颜色。
# case05_mask_color.py from wordcloud import WordCloud, ImageColorGenerator from PIL import Image import numpy as np import matplotlib.pyplot as plt import jieba from common import read_text, FONT text = ' '.join(jieba.cut(read_text('data/book.txt'))) mask = np.array(Image.open('masks/color_mask.png')) wc = WordCloud(mask=mask, font_path=FONT, mode='RGBA', background_color=None).generate(text) # 从彩色蒙版里提取颜色,再重新着色;顺序不能反,必须在 generate 之后 image_colors = ImageColorGenerator(mask) wc.recolor(color_func=image_colors) plt.imshow(wc, interpolation='bilinear') plt.axis('off') plt.show() wc.to_file('outputs/case05.png')recolor的调用时机是硬约束:它改的是已经排好版的词的字体颜色,如果放在generate之前,词还没生成,改了也是白改。这一条在排查颜色失效时排第一位。
3.4 案例 06-07:自定义颜色函数与权重驱动
案例 06 把取色逻辑从“跟着图片走”换成“自己算”。color_func接收一个回调,参数里有词、字号、位置、方向等,返回一个颜色字符串,HSL 写法在控制亮度上比 RGB 更直观。
# case06_color_func.py import random from wordcloud import WordCloud from PIL import Image import numpy as np import matplotlib.pyplot as plt import jieba from common import read_text, FONT text = ' '.join(jieba.cut(read_text('data/book.txt'))) mask = np.array(Image.open('masks/color_mask.png')) def random_color(word, font_size, position, orientation, font_path, random_state): """固定饱和度与亮度区间,只让色相随机,整张图不会花掉""" return 'hsl(0, %d%%, %d%%)' % ( random.randint(60, 80), # 饱和度 60%~80% random.randint(60, 80), # 亮度 60%~80% ) wc = WordCloud( color_func=random_color, mask=mask, font_path=FONT, mode='RGBA', background_color=None, ).generate(text) wc.to_file('outputs/case06.png')这个函数的签名是 WordCloud 规定的,六个参数顺序不能改,但你不一定全用。案例里色相固定为 0(红系),只让饱和度和亮度抖动,得到的是同一色系的深浅变化;想换色系就把第一个 0 改成 200(蓝系)或 120(绿系)。如果三个通道全随机,图会变得像打翻的调色盘,正式报告里不建议这么做。
案例 07 是全篇的收口:不再按词频定字号,而是先用 TF-IDF 抽出关键词和权重,再把字典直接喂给词云。
# case07_tfidf.py from wordcloud import WordCloud, ImageColorGenerator from PIL import Image import numpy as np import matplotlib.pyplot as plt import jieba.analyse from common import read_text, FONT text = read_text('data/book.txt') # topK 控制取前多少个词,withWeight 让返回值带上权重 freq = jieba.analyse.extract_tags(text, topK=200, withWeight=True) print(freq[:20]) # 先看前 20 个词合不合理 freq = {i[0]: i[1] for i in freq} # 转成 {词: 权重} 字典 mask = np.array(Image.open('masks/color_mask.png')) wc = WordCloud( mask=mask, font_path=FONT, mode='RGBA', background_color=None, ).generate_from_frequencies(freq) # 注意:这里不用 generate image_colors = ImageColorGenerator(mask) wc.recolor(color_func=image_colors) wc.to_file('outputs/case07.png')这里换成了generate_from_frequencies,它接收的是字典而不是原始文本,意味着分词、去停用词、算权重全在外部完成,WordCloud 只负责排版。topK=200是个经验值:太少图会稀疏,太多小词挤在一起看不清,200 上下通常能兼顾信息量和观感。extract_tags默认用 TF-IDF,词在本文档里出现得多、在整个语料里出现得少,权重就高,比单纯数词频更能反映主题词。
4. 关键参数与数据流:WordCloud 对象内部到底发生了什么
4.1 画布参数:width、height、mode、background_color 怎么配
这几个参数经常被当成“随便填填”,实际上它们互相牵制。传了mask之后width/height失效;mode='RGBA'只有在background_color=None时才有意义,两者要一起写才能拿到透明背景;如果只写background_color=None但 mode 还是默认的RGB,导出的图背景会是黑的。
| 参数 | 默认值 | 作用 | 常见改法 |
|---|---|---|---|
| width / height | 400 / 200 | 无 mask 时的画布像素尺寸 | 800x600,兼顾清晰度和排布速度 |
| mask | None | 词的可绘制区域 | 传 ndarray,尺寸别超过 2000px |
| mode | 'RGB' | 输出色彩模式 | 要透明背景时改 'RGBA' |
| background_color | 'black' | 背景色 | 与 mode='RGBA' 搭配时写 None |
| font_path | None | 字体文件路径 | 中文必填,指向 ttf/otf |
| max_words | 200 | 最多显示多少个词 | 长文本可提到 300~500 |
| stopwords | None | 要排除的词集合 | 中文需自备停用词表 |
max_words值得单独说一句。它限制的是进入排版的词的种类数,不是出现次数。文本很长时,把max_words从 200 提到 500,图会明显变密,但排布耗时也会上去;如果只是想让人看清主题,200 完全够用,堆得太满反而没人愿意看。
4.2 generate 与 generate_from_frequencies 的分工
这两个方法是最容易被混用的一对。generate(text)接收一段用空格分好词的字符串,内部自己统计词频;generate_from_frequencies(dict)接收一个现成的{词: 权重}字典,跳过分词和统计。
# 两条路径的输入形态完全不同,混用会直接报错 wc.generate('词1 词2 词3') # 输入:空格分隔的字符串 wc.generate_from_frequencies({'词1': 0.8, '词2': 0.3}) # 输入:字典选择依据很简单:数据源已经做过分词、或者权重来自 TF-IDF 这类外部算法,就用generate_from_frequencies;只是想把一段文本快速可视化,就用generate。前者的可控性明显更强——你可以手动往字典里加词、调权重、剔除不想出现的词,而generate里的停用词过滤只能靠stopwords参数,粒度粗得多。做正式交付时我更倾向后者,因为图上的每一个词都是自己确认过的。
4.3 颜色链路:mask 取色、color_func、recolor 三者的执行顺序
颜色这条链上有三个角色,顺序错了就出不来效果。正确的执行次序是:先generate(或generate_from_frequencies)把词排好,再决定颜色,最后to_file落盘。
wc.generate(text) # 第一步:排词 image_colors = ImageColorGenerator(mask) # 第二步:准备取色器 wc.recolor(color_func=image_colors) # 第三步:着色 wc.to_file('outputs/final.png') # 第四步:落盘ImageColorGenerator取的是蒙版对应像素位置的 RGB 值,所以它要求蒙版必须是彩色的三通道图。如果蒙版是一张灰度图(mode 为L),取出来全是灰阶,效果会非常寡淡;如果蒙版带 alpha 通道,np.array出来是四通道,部分版本的 wordcloud 会直接抛形状异常。稳妥做法是读进来后统一Image.open(...).convert('RGB')再转数组。
color_func和recolor是同一件事的两种写法:构造时传color_func=,等价于生成后调recolor(color_func=...)。前者写起来更紧凑,后者在需要“先生成再决定配色”的场景里更灵活,我一般用后者,因为改配色时不用重跑排布。
4.4 输出落盘:to_file、尺寸与清晰度的关系
wc.to_file()直接按对象内部的画布尺寸出图,没有额外的 DPI 参数可调。想要更清晰的成品图,只有两条路:把width/height调大,或者把蒙版图本身做大。这不是玄学,是 wordcloud 的输出机制决定的——它输出的是像素图,画布多大图就多大。
# 想要 2 倍清晰度:把画布和蒙版一起放大,字体同步变细 wc = WordCloud(mask=mask, font_path=FONT, width=1600, height=1200, mode='RGBA', background_color=None, max_font_size=200) wc.generate(text) wc.to_file('outputs/hd.png') # 尺寸随之变成 1600x1200 左右放大画布后要同步调max_font_size,否则最大的词会顶满画布边缘,被裁掉一部分。outputs/目录记得先在脚本里建好,to_file不会自动创建父目录,路径不存在时报的是FileNotFoundError,看起来像 wordcloud 的问题,其实是路径问题。
5. 避坑与排查:中文乱码、蒙版全黑、颜色失效的处理顺序
5.1 中文全是方块,或者整段文本糊成一坨
现象:图上确实有词,但每个字都是空心方块,或者只有寥寥几个巨大到看不清的词块。
原因:前者是font_path没生效——要么路径写错但没报错(部分环境下会静默回退到默认字体),要么字体文件本身不含中文。后者是中文没做分词,整段话被当成一个“词”,字号被撑到极大。
解决:先在代码里print(os.path.exists(FONT))确认字体文件真的在,再print(text[:100])确认分词输出里带空格。两条都过了还出方块,换一个确定含中文字形的 ttf 再试。中文场景下core的两步(字体 + 分词)缺一不可,只补其中一步是没用的。
5.2 蒙版出来一片空白,或者背景全是黑的
现象:传了 mask 之后,图上要么只剩零星几个词,要么整个背景被填成黑色。
原因:一是 mask 的像素语义反了,WordCloud 把接近白色的区域当作不可绘制区,很多人凭直觉把主体画成白色,结果主体位置一个词都没有。二是background_color=None和mode没配套,默认RGB模式下给None会得到黑底。
解决:把蒙版重新导出,主体涂成纯黑或深色,背景纯白,存成不带 alpha 的 PNG。背景透明则固定写成mode='RGBA', background_color=None这两行一起。判断蒙版有没有问题,最快的方式是plt.imshow(mask)先把蒙版本身显示出来看一眼,别靠猜。
5.3 取色完全没效果,词还是单色
现象:调了ImageColorGenerator,但图上的词颜色和蒙版对不上,或者干脆全是同一种颜色。
原因:八成是recolor写在了generate之前;剩下两成是蒙版是灰度图或四通道图,取不到有效的 RGB 值。
解决:把顺序固定成“先生成、再 recolor、最后 to_file”,蒙版读入时统一.convert('RGB')。另外ImageColorGenerator的取色是基于词的落点位置去采蒙版对应像素,蒙版尺寸和画布差距太大时颜色会很集中,把蒙版裁到和预期画布接近的比例,效果会自然很多。
5.4 词云里全是“的、了、是”,关键词被挤没了
现象:图很大、词很多,但最显眼的都是虚词,真正想突出的名词反而很小。
原因:中文分词后高频虚词天然占据词频榜首,stopwords参数默认只对英文有效,中文停用词不会自动过滤。
解决:自备一份停用词表,按行读取成 set,在分词阶段和stopwords=参数里各过一遍。更彻底的做法是走案例 07 的 TF-IDF 路线,虚词虽然词频高,但在文档间的区分度低,权重自然被压下去,这一步比手工剔除停用词更稳。
5.5 脚本跑了几分钟还不出图
现象:命令行卡住不动,CPU 占满,内存缓慢上涨。
原因:蒙版尺寸太大(比如 4000x3000),或者max_words设到了上千,排布算法要在有限区域内为每个词找不重叠的位置,词越多、空间越大,耗时增长非常快。
解决:蒙版宽度控制在 2000px 以内,max_words控制在 200~500。真要出高清大图,先用小尺寸参数调好效果,确认无误后再放大跑一次,别在小尺寸上反复试错的同时还扛着大画布的耗时。
5.6 一份从上到下的排查顺序
出问题时不要同时改三处,按下面的顺序单点推进,每次只改一个变量:
- 先跑案例 01,确认环境和库版本没问题;
- 换成中文文本,确认字体路径生效(看是否出方块);
- 加分词,打印前 100 字符肉眼检查切词质量;
- 加 mask,先
imshow(mask)看蒙版本身对不对; - 加取色,确认
recolor在generate之后; - 最后调
max_words和画布尺寸,优化观感。
这个顺序的价值在于:任何一步出错,问题一定出在刚加的那一步,不会跟前面的环节混在一起。血泪经验是,多数人出问题后的第一反应是同时改字体、改分词、改蒙版,改完发现好了,但不知道为什么好,下次遇到同类问题还是不会。
6. 验收与答辩:用一张对照表证明词云不是随手跑的
词云这类可视化最容易在答辩现场被问倒的一句话是:“这张图好看,但它说明了什么?”如果答不上来,前面所有的参数调试都会被判定成“调包”。我在交这类作业前会强制自己走一遍下面这张对照表,六个检查项全部能回答,才允许自己导出最终图。
| 检查项 | 合格标准 | 现场怎么答 |
|---|---|---|
| 分词质量 | 抽前 20 个词,没有明显被切断的专名 | 展示自定义词典或cut的过滤逻辑 |
| 停用词 | 图上找不到“的、了、是”这类虚词 | 说明停用词表来源和过滤位置 |
| 权重口径 | 字号大小有明确依据(词频或 TF-IDF) | 指出用的是generate还是generate_from_frequencies |
| 蒙版语义 | 主体区域有色,背景干净 | 现场imshow(mask)展示原始蒙版 |
| 配色依据 | 颜色来自蒙版取色或自定义函数,不是随机 | 打开color_func或ImageColorGenerator那段 |
| 可复现性 | 换机器、换目录能跑出同一张图 | 路径基于脚本位置,字体随项目走 |
这六项里,最容易被忽略的是最后一项。评审老师如果当场让你换一个目录跑一遍,路径写死成绝对路径的脚本会立刻露馅,而这一条恰恰是“能不能当模板复用”的分水岭。我的习惯是把data/、fonts/、masks/三个目录跟代码一起打包,common.py里所有路径都基于os.path.dirname(os.path.abspath(__file__))拼出来,交付时整个目录拷走就能跑。
另一个高频追问是“为什么不用现成的在线词云工具”。这个问题的答案不在工具本身,而在可控性:在线工具拿不到分词这一层,也没法按 TF-IDF 权重出图,做舆情或报告时你想剔除某几个词、想突出某几个词,它做不到。案例 07 的字典输入方式才是能写进方案的形态——权重从哪来、词表怎么定,全在代码里,每一步都能被追问、被复现。
答辩现场还有一个小技巧:不要只展示最终那张图,把案例 01 到 07 的七张图并排放在一页 PPT 上,从“最简调用”讲到“权重驱动”,每一张对应一个新变量。这比讲十分钟原理更有说服力,因为它直接证明了整个过程是可控的、每一步都有据可查。从那以后我每次交这类可视化作业,都强制自己先把这七张图按顺序跑一遍再动手写报告,因为图上任何一个不自然的细节,都会在答辩时变成第一个被问到的问题。希望帮到你。
本文还有配套的精品资源,点击获取