Python Matplotlib绘制折线图如何避免标注文本与线条重叠
问题描述
我尝试使用x_tn、y_tn列表存储的数值作为(x,y)坐标绘制折线,以seri列表中的序列值作为各数据点的文本标注,简化实现代码如下。但运行后发现标注(1)、(6)等多处位置的文本与折线发生重叠,需要实现标注自动避让折线的通用设置。
原有实现代码:
import matplotlib.pyplot as plt plt.style.use('seaborn-whitegrid') import numpy as np x_tn = [0,1,1,2,3,2,2] y_tn = [0,0,1,2,1,1,0] seri = [0,1,2,3,4,5,6] plt.title("Function") plt.xlabel("x") plt.ylabel("y") plt.plot(x_tn, y_tn, '-ok') for x,y,k in zip(x_tn,y_tn,seri): label = f"({k})" plt.annotate(label, (x,y), textcoords="offset points", xytext=(0,10), ha='center') plt.xticks(np.arange(min(x_tn), max(x_tn)+1, 1)) plt.yticks(np.arange(min(y_tn), max(y_tn)+1, 1)) plt.show()
问题运行效果示例:
解决方案
Matplotlib 原生没有提供标注自动避让的通用参数,最通用省事的方案是使用第三方库adjustText,它可以自动迭代调整所有标注的位置,避开折线、数据点、其他标注等图内元素,不需要手动为每个点计算偏移量。
- 首先安装依赖:执行命令
pip install adjustText - 改造原有代码:把所有标注对象存入列表,调用
adjust_text方法传入标注列表,同时指定标注和数据点的偏移距离、需要避让的图元(折线、散点等)即可。
改造后的可运行代码:
import matplotlib.pyplot as plt plt.style.use('seaborn-whitegrid') import numpy as np from adjustText import adjust_text x_tn = [0,1,1,2,3,2,2] y_tn = [0,0,1,2,1,1,0] seri = [0,1,2,3,4,5,6] plt.title("Function") plt.xlabel("x") plt.ylabel("y") line, = plt.plot(x_tn, y_tn, '-ok') texts = [] for x,y,k in zip(x_tn,y_tn,seri): label = f"({k})" # 不写死固定偏移,将标注对象统一存储 texts.append(plt.annotate(label, (x,y), ha='center')) # 开启自动避让 adjust_text( texts, # 指定需要避让的图元:折线和对应数据点 add_objects=[line], # 标注距离对应数据点的最小偏移 min_distance=10, # 标注之间、标注和避让图元的最小间距系数 expand_points=(1.2, 1.2), expand_objects=(1.2, 1.2) ) plt.xticks(np.arange(min(x_tn), max(x_tn)+1, 1)) plt.yticks(np.arange(min(y_tn), max(y_tn)+1, 1)) plt.show()
如果不安装第三方库,只能针对当前数据集手动调整每个重叠点的偏移方向,没有通用原生配置可以实现全场景自动避让,更换数据集后需要重新调参,通用性很差。
内容的提问来源于stack exchange,提问作者Rossy Clair
相关产品推荐
相关产品推荐

