是否可以控制 matplotlib 标记方向?
Posted
技术标签:
【中文标题】是否可以控制 matplotlib 标记方向?【英文标题】:Is it possible to control matplotlib marker orientation? 【发布时间】:2014-06-14 06:19:49 【问题描述】:我想知道我是否有一个三角形标记,是否可以控制它的方向?我有一系列面,以及它们对应的顶点,我想绘制它们的底图。我知道在使用 Mayavi 和 tvtk.PolyData 时它是直截了当的脚本。但由于我处理的是地图而不是 3D 对象,所以事情变得有点复杂。
ps:对于地图,我正在使用底图工具。
感谢您的帮助。
【问题讨论】:
【参考方案1】:您可以使用关键字参数marker
创建custom polygons,并向其传递一个由3 个数字组成的元组(number of sides, style, rotation)
。
要创建一个三角形,您可以使用(3, 0, rotation)
,示例如下所示。
import matplotlib.pyplot as plt
x = [1,2,3]
for i in x:
plt.plot(i, i, marker=(3, 0, i*90), markersize=20, linestyle='None')
plt.xlim([0,4])
plt.ylim([0,4])
plt.show()
【讨论】:
打败我——还有一个例子! (+1) 三角形不是等边的吗?我可以传递一个 Nx3 形状的元组,而不是遍历每个方面吗? 使用这种方法,三角形必须是等边的(它会创建一个正多边形,所以如果你通过它 4 它会创建一个正方形)。我不认为 matplotlib 能够创建比它本身更高级的符号。如果您可以生成自己想要的符号作为图像,您可以尝试this 如何制作第三个元素,即旋转 - 一个数据框系列。我根据 , x=df1['A'], y=df1['Speed'] z=df1['Direction'] 进行绘图 @SLE 在我的脑海中浮现,实际上完全一样。您必须逐行遍历数据框并执行plt.plot(df['A'], df['Speed'], marker = (...some calculation that you want that uses df['Direction']...))
。虽然不是很有效(迭代和绘制 N 个像这样的单点)。如果您有 M 个与其他行共享的方向(例如 N、S、E、W),那么您可以按方向索引 df,然后绘制这些索引部分,那么您将有 M 个不同的 plt.plot
调用对于 M 个不同的方向。【参考方案2】:
我只是想添加一种方法来旋转其他非规则多边形标记样式。下面我通过修改marker样式类的transform属性,旋转了“thin diamond”和“plus”和“vline”。
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
for m in ['d', '+', '|']:
for i in range(5):
a1, a2 = np.random.random(2)
angle = np.random.choice([180, 45, 90, 35])
# make a markerstyle class instance and modify its transform prop
t = mpl.markers.MarkerStyle(marker=m)
t._transform = t.get_transform().rotate_deg(angle)
plt.scatter((a1), (a2), marker=t, s=100)
【讨论】:
我注意到plt.plot
不接受 MarkerStyle 对象,它会抛出错误:TypeError: float() argument must be a string or a number, not 'MarkerStyle'
。 plt.scatter
工作正常。【参考方案3】:
看看matplotlib.markers 模块。特别有趣的是,您可以使用具有指定角度的任意多边形:
marker = (3, 0, 45) # triangle rotated by 45 degrees.
【讨论】:
【参考方案4】:自定义matplotlib.path.Path
(不规则三角形)的解决方案
如果您寻找一个标记符号,您可以清楚地从 [0, 2pi) 拒绝方向,您可以构造一个marker from a path。 由于路径由绘图例程自动缩放(使得最外点接触框 -1
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
def gen_arrow_head_marker(rot):
"""generate a marker to plot with matplotlib scatter, plot, ...
https://matplotlib.org/stable/api/markers_api.html#module-matplotlib.markers
rot=0: positive x direction
Parameters
----------
rot : float
rotation in degree
0 is positive x direction
Returns
-------
arrow_head_marker : Path
use this path for marker argument of plt.scatter
scale : float
multiply a argument of plt.scatter with this factor got get markers
with the same size independent of their rotation.
Paths are autoscaled to a box of size -1 <= x, y <= 1 by plt.scatter
"""
arr = np.array([[.1, .3], [.1, -.3], [1, 0]]) # arrow shape
angle = rot / 180 * np.pi
rot_mat = np.array([
[np.cos(angle), np.sin(angle)],
[-np.sin(angle), np.cos(angle)]
])
arr = np.matmul(arr, rot_mat) # rotates the arrow
# scale
x0 = np.amin(arr[:, 0])
x1 = np.amax(arr[:, 0])
y0 = np.amin(arr[:, 1])
y1 = np.amax(arr[:, 1])
scale = np.amax(np.abs([x0, x1, y0, y1]))
arrow_head_marker = mpl.path.Path(arr)
return arrow_head_marker, scale
fig, ax = plt.subplots()
for rot in [0, 15, 30, 45, 60, 90, 110, 180, 210, 315, 360]:
marker, scale = gen_arrow_head_marker(rot)
markersize = 25
ax.scatter(rot, 0, marker=marker, s=(markersize*scale)**2)
ax.set_xlabel('Rotation in degree')
plt.show()
【讨论】:
【参考方案5】:我认为有更好更全面的答案as for Matplotlib 3.3.3:
有一个选项“verts”用于指定标记,它具有 (x,y) 元组列表的形式,这些元组是路径的顶点。这允许您绘制几乎任何形状的标记,填充与否,打开或关闭等。据我测试,其他标记选项(见下文)仍然适用。
例如
plt.plot(x,y,
marker=[(0,-24),(-10,-20),(10,-16),(-10,12),(10,8),(0,-4),(0,0)],
markersize=42, color='w', linestyle='None',
markeredgecolor='k', markeredgewidth= 2.)
将创建一个弹簧形状的标记。大小会自动映射到单位正方形,您的点 (0,0) 将放置在 x,y 处。 从这里开始,制作一个函数来旋转给定角度整个坐标列表应该是一项微不足道的任务。
【讨论】:
以上是关于是否可以控制 matplotlib 标记方向?的主要内容,如果未能解决你的问题,请参考以下文章