如何在 matplotlib 中用箭头绘制轴

问题描述 投票:0回答:3

我想实现以下三件事:

  • 在 x 和 y 轴上添加箭头
  • 仅显示使用的值
  • 添加坐标标签

此时我的代码:

x = [9, 8, 11, 11, 14, 13, 16, 14, 14]
y = [9, 16, 15, 11, 10, 11, 10, 8, 8]
fig = plt.figure(figsize=(7,7), dpi=300)
axes = fig.add_axes([0,1,1,1])

axes.set_xlim(0, 17)
axes.set_ylim(0, 17)

axes.invert_yaxis()

axes.scatter(x, y, color='green')
axes.vlines(x, 0, y, linestyle="dashed", color='green')
axes.hlines(y, 0, x, linestyle="dashed", color='green')
axes.spines.right.set_visible(False)
axes.spines.bottom.set_visible(False)

plt.show()

视觉上:

enter image description here

还有我想实现的剧情 enter image description here

python matplotlib
3个回答
3
投票

您可以通过在脊柱末端叠加三角形点来绘制箭头。

您需要利用一些

transforms
,但您也可以通过手动向
Axes
对象添加文本来创建标签。

可以通过 axes.annotate 来标记每个坐标,但您需要手动指定每个注释的位置,以确保它们不会与线条或其他注释重叠。

import matplotlib.pyplot as plt
from matplotlib.ticker import FixedLocator

x = [9, 8, 11, 11, 14, 13, 16, 14, 14]
y = [9, 16, 15, 11, 10, 11, 10, 8, 8]

fig = plt.figure(figsize=(7,7), dpi=300)
axes = fig.add_axes([.05,.05,.9,.9])

# Plots the data
axes.scatter(x, y, color='green')
axes.vlines(x, 0, y, linestyle="dashed", color='green')
axes.hlines(y, 0, x, linestyle="dashed", color='green')

axes.set_xlim(0, 17)
axes.set_ylim(0, 17)
axes.set_xticks(x)
axes.set_yticks(y)
axes.invert_yaxis()

# Move ticks to top side of plot
axes.xaxis.set_tick_params(
    length=0, bottom=False, labelbottom=False, top=True, labeltop=True
)
axes.xaxis.set_tick_params(length=0)

# Add arrows to the spines by drawing triangle shaped points over them
axes.plot(1, 1, '>k', transform=axes.transAxes, clip_on=False)
axes.plot(0, 0, 'vk', transform=axes.transAxes, clip_on=False)
axes.spines[['bottom', 'right']].set_visible(False)

# Add labels for 0, F_1 and F_2
from matplotlib.transforms import offset_copy
axes.text(
    0, 1, s='0', fontstyle='italic', ha='right', va='bottom',
    transform=offset_copy(axes.transAxes, x=-5, y=5, fig=fig, units='points'),
)
axes.text(
    1, 1, s='$F_1$', fontstyle='italic', ha='right', va='bottom',
    transform=offset_copy(axes.transAxes, x=0, y=5, fig=fig, units='points'),
)
axes.text(
    0, 0, s='$F_2$', fontstyle='italic', ha='right',
    transform=offset_copy(axes.transAxes, x=-5, y=0, fig=fig, units='points'),
)

# Add labels at each point. Leveraging the alignment of the text
# AND padded offset.
lc = ('top', 'center', 0, -5)
ll = ('top', 'right', -5, -5)
lr = ('top', 'left', 5, -5)
ur = ('bottom', 'left', 5, 5)
alignments = [lc, lc, lc, ll, lc, ll, lc, ur, lr]
for i, (xc, yc, (va, ha, padx, pady)) in enumerate(zip(x, y, alignments)):
    axes.annotate(
        xy=(xc, yc), xytext=(padx, pady),
        text=f'$F(x_{i})$', ha=ha, va=va, textcoords='offset points')

plt.show()

enter image description here


1
投票

添加

axes.plot(1, 0, ">k", transform=axes.get_yaxis_transform(), clip_on=False)  
axes.plot(0, 0, "vk", transform=axes.get_xaxis_transform(), clip_on=False)

会为你做的。这基本上只是标记的作弊图。


还有

from mpl_toolkits.axisartist.axislines.AxesZero
这允许

for direction in ["xzero", "yzero"]:
    # adds arrows at the ends of each axis
    ax.axis[direction].set_axisline_style("-|>")

但是他们无法使用默认设置处理您的情况下的反向 y 轴。


0
投票

在寻找一种在轴上制作箭头的方法时遇到了这个问题,但我想控制箭头的纵横比,您可以使用上面的答案进行稍微修改。

您定义 (a) 一个

Affine2D
缩放变换 (
mpl.transforms.Affine2D().scale(sx,sy)
) 并 (b) 使用该变换 (
MarkerStyle
) 来使用
mpl.markers.MarkerStyle()
。此变换独立于使用轴坐标的坐标变换(例如
ax.get_xaxis_transform()
)。对每个轴执行一次此操作。请参阅此页面例如

带有 2:1 长度:宽度箭头的示例:

# Arrows on axes
# We'll stretch out the triangular markers
stretchxax = mpl.transforms.Affine2D().scale(sx=2.,sy=1.)
stretchyax = mpl.transforms.Affine2D().scale(sx=1.,sy=2.)
ax.plot(1,0,'k',marker=mpl.markers.MarkerStyle('>',transform=stretchxax),transform=ax.get_yaxis_transform(),clip_on=False)
ax.plot(0,1,'k',marker=mpl.markers.MarkerStyle('^',transform=stretchyax),transform=ax.get_xaxis_transform(),clip_on=False)
© www.soinside.com 2019 - 2024. All rights reserved.