plot marker 密度过大怎么办
鉴于多数代码比较简单,本文的示例源代码就不全部放上来了,那样太长。需要的可以下载完整的 .ipynb 文件,包含了每一步的示例源代码,下载地址:https://download.csdn.net/download/sinat_32570141/14052756
日前,Python草堂群的一位网友用pyplot.plot
绘制的图形,开启 marker
后,由于 points 密度太大, marker 堆叠在了一起,想少标注一些点,问应该怎么办?
推荐两个方法:
- 因为他是科研中的绘图,首先推荐了提取数据的子集,绘制第二个点图。
- 其次推荐使用
pyplot.plot
的markevery
参数。
他用第 1 个方法后,反馈说,那样会再绘制一条线,那不是他想要的。最后他选择了第二个方法。这里反映了很多人对 matplotlib 绘图的认识、思维上的不足。
有感而发,就从 maker
密度过大,应该如何处理,聊聊 matplotlib 绘图中多个解决方案如何选择的问题。
先顺带详细总结一下 pyplot.plot(x,y, markevery)
的 markevery
参数设置。
下图是两种设置方法的比较:
marker 密度过大的示例
marker=None
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
x=np.arange(0,2*np.pi,0.01)
y=np.sin(x)
fig, ax = plt.subplots(constrained_layout=True)
plt.title('markevery=None')
ax.plot(x, y, marker=None, mec='r')
plt.savefig('.\\assets\\handle_marker01.png',facecolor='w')
plt.show()
设置 marker = ‘o’
变成了这样:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
delta = 0.11
x = np.linspace(0, 10 - 2 * delta, 200) + delta
y = np.sin(x) + 1.0 + delta
fig, ax = plt.subplots(constrained_layout=True)
plt.title('markevery=\'o\'')
ax.plot(x, y, marker='o', mfc='r',mec='r')
plt.savefig('.\\assets\\handle_marker02.png',facecolor='w')
plt.show()
可以:
设置 markevery=10
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
x=np.arange(0,2*np.pi,0.01)
y=np.sin(x)
fig, ax = plt.subplots(constrained_layout=True)
plt.title('markevery=10')
ax.plot(x, y, marker='o', markevery=10, mfc='r',mec='r')
plt.savefig('.\\assets\\handle_marker03.png', facecolor='w')
plt.show()
markevery 参数详解
markevery
参数来源于 matplotlib.lines
模块的 .Line2D
类。
line2D
类设计了一个关键字参数 markevery
,并提供了一个 set_markevery(self, every)
方法用于设置该参数,还提供了一个 get_markevery(self)
参数用于返回 markevery
的设置。
pyplot.plot()
函数就是对 Line2D
对象的封装,它返回一个 Line2D
对象列表。
markevery 参数的允许形式
提示: markevery
就是设置 Line2D set_markevery(self, every)
方法的 every
参数。
- None
- int
- (int, int)
- slice
- List[int]
- float
- (float, float)
- List[bool]
这些设置定义在哪些位置放置 marker
:
every=None
全部数据点都将被标记。
every=N
从 0 位开始,依次第 N 个点将被标记。
every=(start, N)
从 start
开始,依次第 N 个点 marker。
every=slice(start, end, N)
在 [start
, end
] 这个区间内依次标记第 N 个点。不包括 end
。
every=[i, j, m, n]
仅标记 i, j, m, n 点。
注意: x 是一个 numpy.array, 或 list。 [i, j, m, n]
,提供的是数组或列表的索引值,而不是 x 值。
every=[True, False, True]
True 对应位置的点将绘制 marker.
注意: 提供的 bool 值列表的长度须与数据的长度一致。否则会报错。
every=0.1,
一个 float,将沿着这条线以大约相等的距离间隔标记,marker 之间沿直线的距离由限定 axes 的 box 的对角线的显示坐标(display-coordinate)距离乘以every的值来确定。
every=(0.5, 0.1)
长度为 2 的 float 数 tuple, 与 every=0.1 的作用相似,但第一个 marker 在 0.5 乘 line 的显示坐标对角线距离 (display-coordinate-diagonal-distance)。
换一种思路, plot + scatter
设置 markevery 参数的方法具有局限性,只能设置 marker 的几个属性,要进一步控制 marker 需要枚举 markers 集,将大大增加代码量。
- marker
- markeredgecolor
- markeredgewidth
- markerfacecolor
- markerfacecoloralt
- markersize
实际上,marker 的本质就是对 (x, y) 数据集的子集进行绘图,我们完全可以提取数据集的子集,叠加绘制一个 scatter
图,全面自由控制各个标记点。
注意: 不要再用 pyplot.plot
, 而应该用 pyplot.scatter()
。
如下例,我们可以对 scatter 图应用 cmap:
另一例:
–End–