在Python的matplotlib中跨子图绘制网格

25

我尝试了以下操作:

d = [1,2,3,4,5,6,7,8,9]
f = [0,1,0,0,1,0,1,1,0]
fig = plt.figure()
fig.set_size_inches(30,10)
ax1 = fig.add_subplot(211)
line1 = ax1.plot(d,marker='.',color='b',label="1 row")
ax2 = fig.add_subplot(212)
line1 = ax2.plot(f,marker='.',color='b',label="1 row")
ax1.grid()
ax2.grid()
plt.show()

我得到了以下输出:

output

但我期望得到以下输出:
expected output 我怎样才能在这两个图之间添加网格线?

可能是在两个子图之间绘制线条的重复问题。 - SpghttCd
@SpghttCd 那是针对Matlab的。这个问题要求使用Python。 - DavidG
抱歉,我知道在过去几个月里有一个关于Matplotlib的问题,所以我选择得太快了。 - SpghttCd
这个链接在这里可能会有所帮助。虽然它不是格线,但你可以把它们变成黑色和细的,使它们看起来像一个。 - Sheldore
@DavidG:我不会称其为重复,但是相似。 - Sheldore
显示剩余2条评论
4个回答

32

没有内置选项来创建子图网格。在这种情况下,我会说一个简单的选择是在后台创建第三个轴,并且该轴具有与x方向上相同的网格,以便可以在两个子图之间看到网格线。

import matplotlib.pyplot as plt

d = [1,2,3,4,5,6,7,8,9]
f = [0,1,0,0,1,0,1,1,0]

fig, (ax1,ax2) = plt.subplots(nrows=2, sharex=True)
ax3 = fig.add_subplot(111, zorder=-1)
for _, spine in ax3.spines.items():
    spine.set_visible(False)
ax3.tick_params(labelleft=False, labelbottom=False, left=False, right=False )
ax3.get_shared_x_axes().join(ax3,ax1)
ax3.grid(axis="x")


line1 = ax1.plot(d, marker='.', color='b', label="1 row")
line1 = ax2.plot(f, marker='.', color='b', label="1 row")
ax1.grid()
ax2.grid()
plt.show()

在此输入图像描述


这是一个很棒的分享。让我试一下。 - Jaffer Wilson

3

这是我的解决方案:

import matplotlib.pyplot as plt

x1 = [1,2,3,4,5,6,7,8,9]
x2= [0,1,0,0,1,0,1,1,0]
x3= range(-10,0)
# frameon=False removes frames
# fig, (ax1,ax2, ax3) = plt.subplots(nrows=3, sharex=True, subplot_kw=dict(frameon=False))
fig, (ax1,ax2, ax3) = plt.subplots(nrows=3, sharex=True)
# remove vertical gap between subplots
plt.subplots_adjust(hspace=.0)

ax1.grid()
ax2.grid()
ax3.grid()

ax1.plot(x1)
ax2.plot(x2)
ax3.plot(x3)

enter image description here

没有框架 subplot_kw=dict(frameon=False):

enter image description here


2
一种选项是创建一个单一的图,然后仅仅偏移数据,因此一个数据集会在另一个上面绘制。

1
谢谢您的回复。请问您能否举个例子呢?因为我已经提供了我要绘制的数据,所以您的回答看起来像是评论。但由于您的分数较低,无法进行评论。如果您能给出一个例子,那对大家会更有帮助。 - Jaffer Wilson

1

解决方案

您可以通过将适当的坐标传递给Line2D来延伸网格线,使用ax1.grid(ydata=[-space_between_axes, 1], clip_on=False)

import matplotlib.pyplot as plt

d = [1,2,3,4,5,6,7,8,9]
f = [0,1,0,0,1,0,1,1,0]
fig = plt.figure()
fig.set_size_inches(30,10)
ax1 = fig.add_subplot(211)
line1 = ax1.plot(d,marker='.',color='b',label="1 row")
ax2 = fig.add_subplot(212)
line1 = ax2.plot(f,marker='.',color='b',label="1 row")
plt.setp(ax1.get_xticklabels(), backgroundcolor="white")  # Eliminate strike-through.
space_between_plots = plt.rcParams["figure.subplot.hspace"]  # <==========
ax1.xaxis.grid(ydata=[-space_between_plots, 1], clip_on=False)  # <==========
ax1.yaxis.grid()
ax2.grid()
plt.show()

enter image description here

这是如何工作的?
根据matplotlib.axis.Axis.grid == ax1.xaxis.grid方法的文档,关键字参数可以传递给Line2DLine2D以x坐标和y坐标(xdataydata)作为参数。
但是使用的是哪个坐标系?您可以使用ax1.get_xgridlines()[-1].get_xydata()来检查。输出结果是array([[9., 0.], [9., 1.]])。显然,x值是数据坐标,y值是轴坐标
下一个问题:需要延伸多远?在这种特殊情况下,您可以直接取数字-1,因为与下面相同线条的重叠是看不见的。然而,正确的方法是获取实际距离,在这种情况下使用space_between_plots = plt.rcParams["figure.subplot.hspace"]。这是0.2,意味着一个图的高度的五分之一。
顶部保持不变,为1
由于Matplotlib默认不在绘图区域外绘制任何内容,所以需要clip_on=True
注意
看起来Matplotlib存在一个bug,在某些情况下使得这个解决方案无法工作。例如,如果我省略plt.setp(...),Matplotlib会抱怨接收到多次ydata参数,并引发TypeError异常。

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