如何使用轴位置作为参考在 matplotlib 上的多个轴上绘制框

问题描述:

我想使用一个斧头坐标作为参考跨多个轴绘制一个框.我拥有的简单代码(不会生成框)是

I would like to draw a box across multiple axes, using one ax coordinates as reference. The simple code I have, that does not generate the box is

import matplotlib.pyplot as plt
import numpy as np

fig, (ax1, ax2) = plt.subplots(2, 1, sharex=False, sharey=False, figsize=(15,9))

x = 2 * np.pi * np.arange(1000) / 1000 
y1 = np.sin(x)
y2 = np.cos(x)

ax1.plot(x,y1)
ax2.plot(x,y2)
plt.show()

生成下图:

我想要的是下图,使用ax2的x坐标来指定位置:

What I would like to have is the following figure, using x cordinates from ax2 to specify the position:

问题是矩形应该起到什么作用.如果它只是一个绑定到 ax2 但延伸到 ax1 上边缘的矩形,则可以像

The question is a bit what purpose the rectangle should serve. If it is simply a rectangle bound to ax2 but extending up to the upper edge of ax1 a rectangle can be created like

import matplotlib.pyplot as plt
import numpy as np

fig, (ax1, ax2) = plt.subplots(2, 1, sharex=False, sharey=False, figsize=(15,9))

x = 2 * np.pi * np.arange(1000) / 1000 
y1 = np.sin(x)
y2 = np.cos(x)

ax1.plot(x,y1)
ax2.plot(x,y2)

rect = plt.Rectangle((1,0), width=1, height=2+fig.subplotpars.wspace,
                     transform=ax2.get_xaxis_transform(), clip_on=False,
                     edgecolor="k", facecolor="none", linewidth=3)
ax2.add_patch(rect)

plt.show()

但是,即使 ax1 的限制发生了变化,它也将保持原样.那是需要的吗?

But that will of course stay where it is, even if the limits of ax1 change. Is that desired?

因此,也许更有趣的解决方案是矩形遵循两个轴上的坐标.以下内容仅适用于matplotlib 3.1,该版本截至今天仅可作为预发行版使用.(pip install --pre --upgrade matplotlib)

So maybe a more interesting solution is one where the rectangle follows the coordinates in both axes. The following would only work in matplotlib 3.1, which is as of today only available as prerelease
(pip install --pre --upgrade matplotlib)

import matplotlib.pyplot as plt
from matplotlib.patches import ConnectionPatch
import numpy as np

fig, (ax1, ax2) = plt.subplots(2, 1, sharex=False, sharey=False, figsize=(15,9))

x = 2 * np.pi * np.arange(1000) / 1000 
y1 = np.sin(x)
y2 = np.cos(x)

ax1.plot(x,y1)
ax2.plot(x,y2)

def rectspan(x1, x2, ax1, ax2, **kwargs):
    line1, = ax1.plot([x1, x1, x2, x2],[0,1,1,0], 
                      transform=ax1.get_xaxis_transform(), **kwargs)
    line2, = ax2.plot([x1, x1, x2, x2],[1,0,0,1], 
                      transform=ax2.get_xaxis_transform(), **kwargs)
    for x in (x1, x2):
        p = ConnectionPatch((x,1), (x,0), 
                            coordsA=ax2.get_xaxis_transform(),
                            coordsB=ax1.get_xaxis_transform(), **kwargs)
        ax1.add_artist(p)

rectspan(1, 2, ax1, ax2, color="k", linewidth=3)
plt.show()