如何提取使用markevery参数绘制的折线中的标记数据点?
这个问题我太有共鸣了!之前用markevery做折线标记时,也踩过get_data()只返回全量数据的坑——毕竟get_data()是获取线条的原始数据源,而markevery只是绘图渲染阶段的筛选规则,根本不会修改底层存储的数据。
你提到用私有方法lines._mark_every_path()解决了问题,确实可行,但我们可以用更通用、更贴近规范的方式来获取标记点坐标,下面两种方案供你参考:
解决方法
方法一:借助matplotlib内部工具函数(推荐)
matplotlib内部有一个专门处理markevery索引计算的工具函数matplotlib.markers._get_markevery_indices,它是处理markevery规则的核心逻辑,比lines._mark_every_path更专注于索引筛选,不需要涉及路径绘制的额外逻辑。
示例代码:
import numpy as np from matplotlib import pyplot as plt import matplotlib.markers as markers # 生成数据并绘制带markevery的折线 x = np.arange(100) y = x**2 line, = plt.plot(x, y, marker='o', markevery=(0, 0.1)) # 获取markevery参数和数据总长度 markevery_config = line.get_markevery() total_points = len(x) # 计算标记点的索引 mark_indices = markers._get_markevery_indices(total_points, markevery_config) # 提取标记点的坐标 mark_x = x[mark_indices] mark_y = y[mark_indices] # 验证:这里应该得到10个点(0,10,20...90) print(len(mark_x)) # 输出10 assert len(mark_x) != 100
这个函数能处理所有合法的markevery参数类型(整数、浮点数、元组、索引列表等),完全遵循matplotlib的官方规则,稳定性很高,是目前最省心的方案。
方法二:自行实现markevery规则(无内部依赖)
如果你完全不想依赖下划线开头的内部函数,可以自己实现markevery的筛选逻辑,覆盖常见的参数场景:
import numpy as np def calculate_markevery_indices(total_points, markevery): if isinstance(markevery, tuple): # 处理(start, step)形式的元组,支持比例或整数步长 start, step = markevery if isinstance(step, float): # 比例步长转换为实际步长 step = int(step * total_points) mark_indices = np.arange(start, total_points, step) elif isinstance(markevery, int): # 每N个点取一个 mark_indices = np.arange(0, total_points, markevery) elif isinstance(markevery, float): # 按比例取点,比如0.1就是取10%的点 point_count = int(total_points * markevery) mark_indices = np.linspace(0, total_points - 1, point_count).astype(int) elif isinstance(markevery, (list, np.ndarray)): # 直接传入的索引列表 mark_indices = np.asarray(markevery) else: raise ValueError(f"不支持的markevery参数类型:{type(markevery)}") return mark_indices # 使用示例 line, = plt.plot(np.arange(100)**2, marker='o', markevery=(0, 0.1)) x, y = line.get_data() mark_indices = calculate_markevery_indices(len(x), line.get_markevery()) mark_x = x[mark_indices] mark_y = y[mark_indices]
这种方式完全自主可控,不需要依赖matplotlib的内部实现,但需要注意:如果未来matplotlib更新了markevery的规则(比如新增了参数类型),你需要同步更新自己的函数逻辑。
内容的提问来源于stack exchange,提问作者xymaxim
相关产品推荐
相关产品推荐

