2012-08-02 179 views
8

我不能够在以下数图绘制一个简单,垂直箭头:Matplotlib:绘制垂直箭头,在双对数坐标

#!/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') 

它只是不显示。从文档中可以看出,所有参数(如宽度,高度等等)都与轴的缩放比例相关。这非常违反直觉。我尝试使用axisartist包的twin()来定义我的顶部的轴,并且限制了(0,1)(0,1)对箭头参数有更多的控制,但我无法弄清楚如何在主要的参数上有一个完全独立的轴。

任何想法?

+1

似乎是matplotlib的问题。尝试'plt.arrow(6e-4,1e-4,0.1,0.2,length_includes_head = True)'并将视图移到y的更高值。你会看到箭头线大约从10-4开始。但是,如果您使用较低的值(即对于x和y,则为1e-5),线消失,并且您只能看到大部分与以前相同的小箭头。 (显然,你应该使用plt.show()来做到这一点) – joaquin 2012-08-02 17:24:54

+0

那么是否有任何解决方法? – janoliver 2012-08-02 17:47:20

+0

如果我知道我会写一个答案;-)。但现在至少你知道箭头在那里...... – joaquin 2012-08-02 17:51:42

回答

4

次要情节接近

创建次要情节做以下

  • 对准位置
  • 使用set_axis_off()打开轴倾斜后(蜱,标签等)
  • 绘制箭头!

所以几行就得到你想要的!

E.g.

#!/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') 

重缩放数据

可选地一个可能更简单的方法,虽然轴标签可能是棘手的,是重新定标该数据。

import numpy 

# Other import commands and data input 

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

不是一个伟大的解决方案,但如果你能处理的刻度标记一个体面的结果!

+0

嗨,我需要一个单独的x和y轴,因为两者都在主机轴上进行日志缩放。 axisartists的'twin'功能总是使用主机和寄生虫轴之间的转换功能。我不希望他们以任何方式连接。由于关于这些事情的文档很差,我找不到一个(可能不是肮脏的)方法来实现这一点。如果它不容易实现,我可能只需在inkscape左右插入箭头即可。 – janoliver 2012-08-02 17:46:00

+0

覆盖。我想不出有两个完全独立的图表,每个图表都有自己的x轴和y轴,等等。 – janoliver 2012-08-02 18:43:40

+0

那么为什么不直接做一个'log(x)'和'log(y)'的线性图?它使绘制箭头微不足道。 – jmetz 2012-08-02 19:02:29

5

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

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

1

我知道这个线程已经死了很长一段时间,但我认为发布我的解决方案可能有助于任何人试图找出如何有效地绘制对数级箭头。

作为别人已发布内容的替代方案,您可以使用transformation object来输入不是原始轴比例的箭头坐标,而是以“轴坐标”的(线性)比例输入。我所说的轴坐标是指那些通过[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)可以为箭头指定,如果你写两个函数fx(x)fy(y)从原始坐标变换,这不是太困难到这些“坐标轴”坐标。我举了一个例子,说明如何修改OP发布的原始代码以实现下面的内容(道歉不包括代码生成的图像,我没有所需的声望)。

#!/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')