我想使用一个斧头坐标作为参考跨多个轴绘制一个框。我有没有生成框的简单代码是
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坐标来指定位置:
答案 0 :(得分:1)
肯定有一个使用Rectangle
补丁的简单方法,但这暂时是一种解决方法。这个想法是要有4条线:2条水平线分别限制为ax1
和ax2
,2条垂直线同时跨越ax1
和ax2
。对于后两个,使用ConnectionPatch
覆盖两个轴。要使用水平线和垂直线的y值的上和下值,请使用get_ylim()
函数。绘制垂直线的想法来自this官方示例和this
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import ConnectionPatch
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)
y_up, y_down = ax1.get_ylim(), ax2.get_ylim()
ax1.hlines(max(y_up), 1, 2, linewidth=4)
ax2.hlines(min(y_down), 1, 2, linewidth=4)
line1 = ConnectionPatch(xyA=[1,min(y_down)], xyB=[1,max(y_up)], coordsA="data", coordsB="data",
axesA=ax2, axesB=ax1, color="k", lw=4)
line2 = ConnectionPatch(xyA=[2,min(y_down)], xyB=[2,max(y_up)], coordsA="data", coordsB="data",
axesA=ax2, axesB=ax1, color="k", lw=4)
ax2.add_artist(line1)
ax2.add_artist(line2)
plt.show()
答案 1 :(得分:1)
问题是矩形应该起到什么作用。如果它只是绑定到ax2
的矩形,但一直延伸到ax1
的上边缘,则可以像这样创建矩形
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
的限制发生了变化,这也将保持不变。那是想要的吗?
因此,也许更有趣的解决方案是矩形遵循两个轴上的坐标。以下内容仅适用于matplotlib 3.1,该版本截至今天仅可作为预发行版
(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()