13

我有以下代码:

from mpl_toolkits.axes_grid.axislines import SubplotZero
from matplotlib.transforms import BlendedGenericTransform
import matplotlib.pyplot as plt
import numpy

if 1:
    fig = plt.figure(1)
    ax = SubplotZero(fig, 111)
    fig.add_subplot(ax)

    ax.axhline(linewidth=1.7, color="black")
    ax.axvline(linewidth=1.7, color="black")

    plt.xticks([1])
    plt.yticks([])

    ax.text(0, 1.05, 'y', transform=BlendedGenericTransform(ax.transData, ax.transAxes), ha='center')
    ax.text(1.05, 0, 'x', transform=BlendedGenericTransform(ax.transAxes, ax.transData), va='center')

    for direction in ["xzero", "yzero"]:
        ax.axis[direction].set_axisline_style("-|>")
        ax.axis[direction].set_visible(True)

    for direction in ["left", "right", "bottom", "top"]:
        ax.axis[direction].set_visible(False)

    x = numpy.linspace(-0.5, 1., 1000)
    ax.plot(x, numpy.sin(x*numpy.pi), linewidth=1.2, color="black")

    plt.show()

这会产生以下图像:

图形

与实际图表相比,轴箭头看起来是退化的。我如何将它们放大一点,以使它们相对于轴的宽度看起来正常。

另外-在这里很难看到,但是箭头的内部是蓝色的-我该如何将其更改为黑色?

4

3 回答 3

11

我的解决方案与 nebffa 的解决方案基本相同。我创建了一个最小的示例,计算 y 轴的箭头宽度和长度以匹配为 x 轴指定的箭头。我希望这可能对其他人有所帮助。

import pylab as pl

fig = pl.figure()
ax = fig.add_subplot(111)

x = pl.arange(-5,5,0.1)
ax.plot(x, x**2-8.8)

xmin, xmax = ax.get_xlim()
ymin, ymax = ax.get_ylim()

# removing the default axis on all sides:
for side in ['bottom','right','top','left']:
    ax.spines[side].set_visible(False)

# removing the axis ticks
pl.xticks([]) # labels
pl.yticks([])
ax.xaxis.set_ticks_position('none') # tick markers
ax.yaxis.set_ticks_position('none')

# wider figure for demonstration
fig.set_size_inches(4,2.2)

# get width and height of axes object to compute
# matching arrowhead length and width
dps = fig.dpi_scale_trans.inverted()
bbox = ax.get_window_extent().transformed(dps)
width, height = bbox.width, bbox.height

# manual arrowhead width and length
hw = 1./20.*(ymax-ymin)
hl = 1./20.*(xmax-xmin)
lw = 1. # axis line width
ohg = 0.3 # arrow overhang

# compute matching arrowhead length and width
yhw = hw/(ymax-ymin)*(xmax-xmin)* height/width
yhl = hl/(xmax-xmin)*(ymax-ymin)* width/height

# draw x and y axis
ax.arrow(xmin, 0, xmax-xmin, 0., fc='k', ec='k', lw = lw,
         head_width=hw, head_length=hl, overhang = ohg,
         length_includes_head= True, clip_on = False)

ax.arrow(0, ymin, 0., ymax-ymin, fc='k', ec='k', lw = lw,
         head_width=yhw, head_length=yhl, overhang = ohg,
         length_includes_head= True, clip_on = False)

# clip_on = False if only positive x or y values.

pl.savefig('arrow_axis.png', dpi = 300)

产生:

在此处输入图像描述

于 2014-05-25T11:59:23.197 回答
7

似乎调用 matplotlib.pyplot.arrow (经过大量校准)可以获得所需的箭头:

plt.arrow(5, -0.003, 0.1, 0, width=0.015, color="k", clip_on=False, head_width=0.12, head_length=0.12)
plt.arrow(0.003, 5, 0, 0.1, width=0.015, color="k", clip_on=False, head_width=0.12, head_length=0.12)

注意坐标的“0.003”偏移量,这是因为由于某种原因 plt.arrow 没有绘制与轴对齐的箭头。真的吗?多么痛苦。

另外值得注意的是clip_on,它允许箭头超出为图形设置的边界(如plt.xlim(-5, 5))。

这个:

from mpl_toolkits.axes_grid.axislines import SubplotZero
from matplotlib.transforms import BlendedGenericTransform
from matplotlib import patches
import matplotlib.pyplot as plt
import numpy

if 1:
    fig = plt.figure(1)
    ax = SubplotZero(fig, 111)
    fig.add_subplot(ax)

    ax.axhline(linewidth=1.7, color="k")
    ax.axvline(linewidth=1.7, color="k")

    plt.xticks([])
    plt.yticks([])

    ax.text(0, 1.05, r'$y$', transform=BlendedGenericTransform(ax.transData, ax.transAxes), ha='center')
    ax.text(1.03, 0, r'$x$', transform=BlendedGenericTransform(ax.transAxes, ax.transData), va='center')

    for direction in ["xzero", "yzero"]:
        ax.axis[direction].set_visible(True)

    for direction in ["left", "right", "bottom", "top"]:
        ax.axis[direction].set_visible(False)

    x = numpy.linspace(-1.499999999, 5, 10000)

    yy = numpy.log(2*x + 3)/2 + 3

    ax.plot(x, yy, linewidth=1.2, color="black")

    plt.ylim(-2, 5)
    plt.xlim(-5, 5)

    plt.arrow(5, -0.003, 0.1, 0, width=0.015, color="k", clip_on=False, head_width=0.12, head_length=0.12)
    plt.arrow(0.003, 5, 0, 0.1, width=0.015, color="k", clip_on=False, head_width=0.12, head_length=0.12)

    plt.text((numpy.e**(-6) - 3)/2, 0, r'$(\frac{1}{2} (e^{-6} - 3), 0)$', position=((numpy.e**(-6) - 3)/2 + 0.1, 0.1))
    plt.plot((numpy.e**(-6) - 3)/2, 0, 'ko')

    plt.text(0, numpy.log(3)/2 + 3, r'$(0, \frac{1}{2} \log_e{\left (3 \right )} + 3)$', position=(0.1, numpy.log(3)/2 + 3 + 0.1))
    plt.plot(0, numpy.log(3)/2 + 3, 'ko')

    plt.savefig('AnswersSA1a.png')

生成如下图:(忽略较差的轴截距标签)

图形

我只是把它作为一个答案,因为这是我看到如何做到这一点的唯一方法。肯定有比手动计算我需要将箭头偏移 0.003 更好的方法。这感觉不对。

于 2013-07-17T02:54:15.957 回答
1

我如何将它们放大一点,以使它们相对于轴的宽度看起来正常[?]

您应该在 set_axisline_style 中添加“size=2”:

ax.axis[direction].set_axisline_style("-|>", size=2)

另外-在这里很难看到,但是箭头的内部是蓝色的-我该如何将其更改为黑色?

这更难。实际上,您必须在运行代码之前覆盖mpl_toolkits.axisartist.axisline_style._FancyAxislineStyle.SimpleArrow.__init__ :

# overwriting
#  mpl_toolkits.axisartist.axisline_style._FancyAxislineStyle.SimpleArrow.__init__
# to have a black color in 
#  mpl_toolkits.axisartist.axisline_style.AxislineStyle.FilledArrow

from matplotlib.transforms import IdentityTransform
from matplotlib.patches import FancyArrowPatch

def new_init(self, axis_artist, line_path, transform,
             line_mutation_scale):
    self._axis_artist = axis_artist
    self._line_transform = transform
    self._line_path = line_path
    self._line_mutation_scale = line_mutation_scale

    FancyArrowPatch.__init__(self,
                             path=self._line_path,
                             arrowstyle=self._ARROW_STYLE,
                             arrow_transmuter=None,
                             patchA=None,
                             patchB=None,
                             shrinkA=0.,
                             shrinkB=0.,
                             mutation_scale=line_mutation_scale,
                             mutation_aspect=None,
                             transform=IdentityTransform(),
                             color='black'  # this line is new
                             )

import mpl_toolkits
mpl_toolkits.axisartist.axisline_style._FancyAxislineStyle.SimpleArrow.__init__ = new_init

要保存图片(plt.show() 或 dpi < 200 将无法正常工作),请使用:

plt.savefig('test.png', dpi=200)

在此处输入图像描述

于 2020-08-18T17:32:52.427 回答