在多个图表上绘制一条线

28

我不知道这个东西叫什么,甚至不知道如何描述它,因此标题可能有点误导。

第一个附加的图是使用pyplot创建的。 我想要绘制一条直线,穿过所有图形,而不是我目前使用的三个红点。 在pyplot中是否可能? 第二张图片就是我要找的。 当前 我要找的


你如何确定在哪里取红点? - Sword22
@Sword22 所有的图表都有相同的x轴。红色点基本上是x轴值的列表。 - Artium
4个回答

38

你可以通过关闭相关线条的裁剪来实现这一点。可能有更简洁的方法来实现这一点 - 你可能能够直接在主框架上绘制线条 - 但以下方法适用于我:

from matplotlib import pyplot as plt
from numpy import arange, sin, cos

xx = arange(100)
cut = (xx > 0) & (xx % 17 == 0)
y1 = sin(xx)
y2 = (xx**2) % 2.0+cos(xx+0.5)

fig = plt.figure()
ax1 = fig.add_subplot(211)
ax1.plot(xx, y1, c="blue",zorder=1)
ax1.scatter(xx[cut], y1[cut], c="red",zorder=2)
ax2 = fig.add_subplot(212)
ax2.plot(xx, y2, c="green",zorder=1)
ax2.scatter(xx[cut], y2[cut], c="red",zorder=2)

for x in xx[cut]:
    ax1.axvline(x=x,ymin=-1.2,ymax=1,c="red",linewidth=2,zorder=0, clip_on=False)
    ax2.axvline(x=x,ymin=0,ymax=1.2,c="red",linewidth=2, zorder=0,clip_on=False)

plt.draw()
fig.savefig('pic.png')

通过一些额外的工作,你可以修改线条绘制来处理多个子图窗口的一般情况,但我非常懒。 :^)

跨子图垂直线的示例


12

相关文档:
http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.axvline

编辑:由于@DSM的回答比我的好太多了,我已经惭愧地借鉴了一些它的内容以使我的回答更好一些。

我已经尝试处理了列中有多个子图的相对通用情况(即不是更加通用的多个图形子图的情况,例如在网格中)。

感谢 @DSM 的答案和 @Artium 的问题。

import matplotlib.pyplot as plt
import numpy as np

def main():
    fig = plt.figure() 

    x = np.arange(20)
    y1 = np.cos(x)
    y2 = (x**2)
    y3 = (x**3)
    yn = (y1,y2,y3)
    cut = (x > 0) & (x % 2 == 0)
    COLORS = ('b','g','k')

    for i,y in enumerate(yn):
        ax = fig.add_subplot(len(yn),1,i+1)

        ax.plot(x, y,ls='solid', color=COLORS[i], zorder=1) 
        ax.scatter(x[cut], y[cut], c='r', zorder=2)

        if i != len(yn) - 1:
            ax.set_xticklabels( () )

        for j in x[cut]:
            if i != len(yn) - 1:
                ax.axvline(x=j, ymin=-1.2, ymax=1,
                           c='r', lw=2, zorder=0, clip_on=False)
            else:
                ax.axvline(x=j, ymin=0, ymax=1,
                           c='r', lw=2, zorder=0, clip_on=False)

    fig.suptitle('Matplotlib Vertical Line Example')
    plt.show()

if __name__ == '__main__':
    main()

这里输入图片描述


我真的很喜欢你的回答。但是,在我的情况下,如果我运行你的代码,水平和垂直边距会出现。有什么办法可以去掉它们吗? - Rickson
更准确地说,在我的情况下,x轴的范围是[-5,20]而不是[0,20],例如对于最后一个图,y轴范围是[-1000,8000]而不是[0,7000]。尝试了几乎所有方法(自动缩放,紧密轴,relim等),但都没有成功。 - Rickson
如果有其他人感兴趣的话:这是由散点生成引起的。 - Rickson
为什么xticklabels的输入值有点奇怪? - Parthiban Rajendran

12

[更新于2013年3月] 在较新版本的 matplotlib 中,有一个 ConnectionPatch 工具,大大简化了此任务。每当需要覆盖两个以上的子图时,它特别有用。

from matplotlib import pyplot as plt
from matplotlib.patches import ConnectionPatch
from numpy import arange, sin, cos

xx = arange(100)
cut = (xx > 0) & (xx % 17 == 0)
y1 = sin(xx)
y2 = (xx**2) % 2.0+cos(xx+0.5)

fig = plt.figure()
ax1 = fig.add_subplot(211)
ax1.plot(xx, y1, c="blue")
ax1.scatter(xx[cut], y1[cut], c="red")
ax2 = fig.add_subplot(212)
ax2.plot(xx, y2, c="green")
ax2.scatter(xx[cut], y2[cut], c="red")

for x in xx[cut]:
    con = ConnectionPatch(xyA=(x, -1.5), xyB=(x, 1.5),
        coordsA="data", coordsB="data", axesA=ax2, axesB=ax1,
        arrowstyle="-", linewidth=2, color="red")
    ax2.add_artist(con)

plt.draw()
fig.savefig('pic.png')

0

我会尝试使用 axvline(x, y1, y2) (link),但我不认为pyplot中的任何选项都能绘制横跨多个子图/图形的内容。

如果是这样的话,我会在图表中的每个点处绘制同一条竖直线,希望能够传达相同的意图给观察者。


抱歉,我的回答并没有提供任何你没有的新信息。我已经准备好了一个例子,所以我还是决定发帖。+1 给你,因为你更快了。 - mechanical_meat
与Jonathan达成一致,带有源代码和示例的答案比没有的答案更好,速度并不重要! - matt b
如果我尝试你的方法,那条线会被隐藏在嵌入轴集后面。我做错了什么? - user3413108

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接