如何优化基于matplotlib实现的词云图的视觉呈现效果
解决方案
移除坐标轴及刻度
前两个需求可以直接通过一行代码同时实现,在plt.show()前添加以下代码即可:
plt.axis('off')
如果仅需要移除刻度数值、保留坐标轴边框,可以改用:
plt.xticks([]) plt.yticks([])
解决单词重叠问题
当前代码直接随机生成文字坐标,没有碰撞校验逻辑,因此会出现重叠问题。可以通过增加边界碰撞检测逻辑解决,实现思路如下:
- 初始化列表存储所有已放置文字的边界框
- 每次生成随机坐标后,先创建临时文字对象,获取它的坐标边界范围
- 校验当前边界和已存储的所有边界是否存在重叠
- 无重叠就正式添加文字到画布,并存入边界列表;有重叠就重新生成坐标,重试指定次数后放弃避免死循环
完整修改后代码
filename = "adventure.txt" wordcounts = {} # 改用with open自动管理文件句柄,避免资源泄漏 with open(filename, 'r', encoding='utf-8') as infile: for line in infile: words = line.split() for word in words: w = "".join([e for e in word if e.isalpha()]) w = w.lower() if not w: # 跳过空字符串 continue wordcounts[w] = wordcounts.get(w, 0) + 1 # 按词频降序排序 words = sorted(wordcounts.keys(), key=lambda x: wordcounts[x], reverse=True) import matplotlib.pyplot as plt import numpy as np # 最高频词字号设为50,原代码用words[1]的话最高频词会超过50字号,可按需调整 scale = 50 / wordcounts[words[0]] plt.axes(xlim=(0, 100), ylim=(0, 100)) # 存储已放置文字的边界框 placed_boxes = [] N = min(len(words), 50) for i in range(N): freq = wordcounts[words[i]] col = ["r", "g", "b", "m", "c", "k"][i % 6] # 原代码取模5,列表有6个颜色,修正为取模6 retry = 0 # 最多重试100次找不重叠的位置 while retry < 100: x = np.random.uniform(0, 90) y = np.random.uniform(0, 90) # 创建临时文本获取边界 temp_text = plt.text(x, y, words[i], fontsize=scale * freq, color=col) # 刷新画布获取准确边界 plt.gcf().canvas.draw() # 转换为数据坐标系的边界框 bbox = temp_text.get_window_extent().transformed(plt.gca().transData.inverted()) # 检查是否和已有文字重叠 overlap = False for existing_box in placed_boxes: if (bbox.x0 < existing_box.x1 and bbox.x1 > existing_box.x0 and bbox.y0 < existing_box.y1 and bbox.y1 > existing_box.y0): overlap = True break if not overlap: placed_boxes.append(bbox) break else: # 重叠就删除临时文本,重试 temp_text.remove() retry += 1 else: # 重试100次仍找不到位置,跳过当前词 temp_text.remove() # 关闭坐标轴 plt.axis('off') plt.show()
如果不需要自己手动实现底层逻辑,也可以直接使用成熟的wordcloud第三方库,只需几行代码就能实现专业的词云布局、配色效果。
内容的提问来源于stack exchange,提问作者fredericoamigo
相关产品推荐
相关产品推荐

