10

我无法在以下对数图中绘制一个简单的垂直箭头:

#!/usr/bin/python2

import matplotlib.pyplot as plt
import matplotlib as mpl

plt.yscale('log')
plt.xscale('log')
plt.ylim((1e-20,1e-10))
plt.xlim((1e-12,1))

plt.arrow(0.00006666, 1e-20, 0, 1e-8 - 1e-20, length_includes_head=True)

plt.savefig('test.pdf')

它只是没有显示。从文档看来,所有参数(如宽度、高度等)似乎都与轴的比例有关。这是非常违反直觉的。我尝试使用twin()axisartist 包在我的顶部定义一个带限制的轴(0,1)(0,1)以更好地控制箭头的参数,但我无法弄清楚如何在主轴之上拥有一个完全独立的轴。

有任何想法吗?

4

3 回答 3

7

我一直在寻找这个问题的答案,并找到了一个有用的答案!您可以指定任何“数学文本”字符(matplotlib 的 LaTeX 版本)作为标记。试试: plt.plot(x,y, 'ko', marker=r'$\downarrow$', markersize=20)

这将在位置 (x,y) 处绘制一个向下指向的黑色箭头,该箭头在任何绘图(甚至对数对数)上看起来都不错。有关您可以使用的更多符号,请参阅:matplotlib.org/users/mathtext.html#mathtext-tutorial。

于 2013-06-14T21:12:06.953 回答
6

子图方法

创建子图后,请执行以下操作

  • 对齐位置
  • 用于set_axis_off()关闭轴(刻度、标签等)
  • 画箭头!

所以几行得到你想要的!

例如

#!/usr/bin/python2

import matplotlib.pyplot as plt

hax = plt.subplot(1,2,1)
plt.yscale('log')
plt.xscale('log')
plt.ylim((1e-20,1e-10))
plt.xlim((1e-12,1))

hax2 = plt.subplot(1,2,2)
plt.arrow(0.1, 1, 0, 1, length_includes_head=True)

hax.set_position([0.1, 0.1, 0.8, 0.8])
hax2.set_position([0.1, 0.1, 0.8, 0.8])

hax2.set_axis_off()

plt.savefig('test.pdf')

重新调整数据

或者,尽管轴标签可能很棘手,但一种可能更简单的方法是重新调整数据。

IE

import numpy 

# Other import commands and data input

plt.plot(numpy.log10(x), numpy.log10(y))) 

不是一个很好的解决方案,但如果您可以处理刻度标签,则效果不错!

于 2012-08-02T17:20:06.213 回答
4

我知道这个线程已经死了很长时间了,但我认为发布我的解决方案可能对任何试图弄清楚如何有效地在对数刻度图上绘制箭头的人有所帮助。

作为其他人已经发布的替代方案,您可以使用转换对象来输入箭头坐标,而不是原始轴的比例,而是“轴坐标”的(线性)比例。我所说的轴坐标是通过 [0,1](垂直范围)归一化为 [0,1](水平范围)的坐标,其中点 (0,0) 是左下角,点(1,1) 将是右上角,依此类推。然后你可以简单地包括一个箭头:

plt.arrow(0.1, 0.1, 0.9, 0.9, transform=plot1.transAxes, length_includes_head=True)

这给出了一个对角线跨越绘图水平和垂直范围的 4/5 的箭头,从左下角到右上角(plot1子图名称在哪里)。

如果您想在一般情况下执行此操作,可以为箭头指定精确坐标(x0,y0)和对数空间,如果您编写两个函数并将原始坐标转换为这些“轴”坐标(x1,y1),这并不难。我已经给出了一个示例,说明如何可以修改 OP 发布的原始代码以在下面实现这一点(抱歉不包括代码生成的图像,我还没有所需的声誉)。fx(x)fy(y)

#!/usr/bin/python3

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

# functions fx and fy take log-scale coordinates to 'axes' coordinates
ax = 1E-12 # [ax,bx] is range of horizontal axis 
bx = 1E0
def fx(x):
    return (np.log(x) - np.log(ax))/(np.log(bx) - np.log(ax))

ay = 1E-20 # [ay,by] is range of vertical axis
by = 1E-10
def fy(y):
    return (np.log(y) - np.log(ay))/(np.log(by) - np.log(ay))

plot1 = plt.subplot(111)
plt.xscale('log')
plt.yscale('log')
plt.xlim(ax, bx)
plt.ylim(ay, by)

# transformed coordinates for arrow from (1E-10,1E-18) to (1E-4,1E-16)
x0 = fx(1E-10)
y0 = fy(1E-18)
x1 = fx(1E-4) - fx(1E-10)
y1 = fy(1E-16) - fy(1E-18)

plt.arrow(
          x0, y0, x1, y1, # input transformed arrow coordinates 
          transform = plot1.transAxes, # tell matplotlib to use axes coordinates   
          facecolor = 'black',
          length_includes_head=True
         )

plt.grid(True)
plt.savefig('test.pdf')
于 2015-09-28T17:18:57.533 回答