Matplotlib 如何在散点图中改进标签位置
在使用matplotlib绘制散点图时,如果数据集比较大,我们需要在图中展示每一个点的标签信息,常常会遇到标签重叠或者有效信息被遮挡,使得图形难以读取的问题。本文将介绍一些方法,通过优化标签的位置,使图形变得清晰易读。
阅读更多:Matplotlib 教程
示例数据
我们将使用python内置库random创建模拟数据集进行演示。
import numpy as np
import random
import matplotlib.pyplot as plt
# 创建模拟数据
x = np.array(np.random.normal(loc=0, scale=10, size=100))
y = np.array(np.random.normal(loc=0, scale=10, size=100))
labels = [random.randint(1,20) for i in range(100)]
绘制图形
fig, ax = plt.subplots(figsize=(10,8))
scatter = ax.scatter(x, y, c = labels)
ax.grid(True)
plt.show()
1. 使用annotate方法
在matplotlib中,annotate方法可使标签在绘图中精确定位,同时可以跨越图形的各种元素(轴线、图形等)。对于大数据集,需要绘制很多标签时,这种方法尤其实用。
annotate方法最重要的两个参数是:xy和xytext。他们分别是被注释点和文本位置的坐标点。
fig, ax = plt.subplots(figsize=(10,8))
scatter = ax.scatter(x, y, c = labels)
ax.grid(True)
for i, txt in enumerate(labels):
ax.annotate(txt, (x[i], y[i]), xytext=(5,5), textcoords='offset points', ha='left', va='top')
plt.show()
我们可以看到,使用annotate方法能够精确的将标签放置到对应散点对应位置,不会产生重叠遮挡现象。
2. 调节字体大小
有时候,标签字体过大也是重复死算或者遮挡的原因之一。在matplotlib中,我们可以设置字体大小(fontsize)、对齐方式(ha、va)等参数,调节标签的字体大小,避免过大过小。
fig, ax = plt.subplots(figsize=(10,8))
scatter = ax.scatter(x, y, c = labels)
ax.grid(True)
for i, txt in enumerate(labels):
ax.annotate(txt, (x[i], y[i]), xytext=(5,5), textcoords='offset points', ha='left', va='top', fontsize=8)
plt.show()
我们可以看到,缩小标签字体大小后,图形更清晰易读。
3. 使用自适应的字体大小方法
当数据集较大时,自适应字体可以自动调整标签的字号,避免重叠遮挡。在使用这种方法之前,需要提前计算每个标签点的最优字体大小和位置,可以通过以下途径进行计算:
from matplotlib.font_manager import FontProperties
fp = FontProperties(size=8)
bbox_props = dict(boxstyle="round,pad=0.3", fc="#ddcaa7", ec="#496165", lw=1.5)
x, y = np.random.normal(size=[2, 100])
labels = [random.randint(1, 20) for i in range(100)]
fig, ax = plt.subplots(figsize=(10,8))
scatter = ax.scatter(x, y, c=labels)
ax.grid(True)
for i, txt in enumerate(labels):
plt.text(x[i], y[i], str(txt), ha='center', va='center', fontproperties=fp, bbox=bbox_props)
plt.show()
可以看到,标签字体大小自适应,同时也能很好地避免标签之间的重叠现象。
4. 使用offsetbox方法
使用offsetbox方法,可以将标签放置在散点周围的固定位置,可以保证标签在不重叠的前提下完整显示,同时不需要手动调整字体大小。
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
fig, ax = plt.subplots(figsize=(10,8))
scatter = ax.scatter(x, y, c = labels)
ax.grid(True)
def get_image(txt):
return OffsetImage(txt, zoom=0.4)
artists = []
for i, txt in enumerate(labels):
ab = AnnotationBbox(get_image(txt), (x[i], y[i]), frameon=False, xybox=(5,5), boxcoords="offset points", ha='left')
artists.append(ax.add_artist(ab))
plt.show()
我们可以看到,使用offsetbox方法能够在不重叠的前提下完整显示标签,同时标签也不会遮挡数据点。
总结
本文介绍了四种在matplotlib中优化标签位置的方法,前三种方法需要手动调整标签位置或字体大小,而第四种方法需要使用特定的工具和技巧,但可以完全自动化。根据需求不同可以选择不同的方法,使图形更加清晰、易读。
极客教程