在Python中创建带有公共线的Matplotlib子图

2 投票
1 回答
762 浏览
提问于 2025-04-18 01:11

我有一个即将到来的作业,需要制作一系列图表,这些图表中有两条曲线,连接着两个图表,并在其中一个图表下方的区域上涂色。

就像这个粗略的草图所示:

enter image description here

这是我目前的成果:

enter image description here

这是我用的代码:

from matplotlib import pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot(121)
ax1.plot([0,1,2,3,4,5,6,7,8,9,10], [1,1,1,1,1,0,0,0,0,0,0], '-b')
ax1.plot([0,1,2,3,4,5,6,7,8,9,10], [0,0,0,0,0,1,1,1,1,1,1], '-r')
ax1.set_ylim([0, 1.2])

ax2 = fig.add_subplot(122)
ax2.plot([0,5,10,15,20,25,30,35,40], [1,1,1,1,0,0,0,0,0], '-b')
ax2.plot([0,5,10,15,20,25,30,35,40], [0,0,0,0,1,1,1,1,1], '-r')
ax2.set_ylim([0, 1.2])

plt.show()

显然,这段代码只生成了两个图表,我还没有办法在这两个图表之间添加那条线。

我真的希望能用Python的Matplotlib来做到这一点,并且能够更改数值(比如示例中的45),这样涂色的区域也能自动变化。

谢谢!

1 个回答

2

这个过程分为三个步骤:第一步,在左边的面板上找到绿色和蓝色线条的交点。第二步,在右边的面板上找到红色线条的交点。第三步,填充这两个交点之间的区域。这些步骤涉及到一些工具,比如 np.interpscipy.interpolatescipy.optimizeplt.fill_between,你可以去查一下这些工具的用法。

from matplotlib import pyplot as plt
import numpy as np
import scipy.interpolate as spinp
import scipy.optimize as spop

fig = plt.figure(figsize=(16,4))
ax1 = fig.add_subplot(121)
x  = [0,10,20,30,40,50,60,70,80,90,100]
yr = [1,1,1,1,1,0,0,0,0,0,0]
yg = [0,0,0,0,0,1,1,1,1,1,1]
turn_pt = np.interp(45, x, yr) #change 45 to whatever.
yb = [0.,turn_pt,turn_pt]
ax1.plot(x, yr, '-r')
ax1.plot(x, yg, '-g')
xb = [45, 45, 200]
ll = plt.plot(xb,yb, '-b')
ll[0].set_clip_on(False) 
plt.axis([0,100,0,1.2])
#the above three lines to draw the line out of the box.

ax2 = fig.add_subplot(122)
yr = [1,1,1,1,0,0,0,0,0]
yg = [0,0,0,0,1,1,1,1,1]
x  = [0,5,10,15,20,25,30,35,40]
brk_pt_f = lambda X, V: (spinp.interp1d(x, yr)(X)-V)**2
brk_pt = spop.fmin(brk_pt_f, 17., args=(turn_pt,), disp=0) #17. is you inital guess,
#the above two lines solve for the intersection between the blue line and the red line
zero_pt = 20.
start_pt= 0.
xb = np.hstack((start_pt, brk_pt, zero_pt))
yb = [turn_pt,turn_pt,0]
ax2.plot(x, yr, '-r')
ax2.plot(x, yg, '-g')
ax2.plot(xb, yb, '-b')
ax2.hlines(turn_pt,0, 40, 'b', alpha=0.)
ax2.fill_between(xb, yb, 0, alpha=0.4)
ax2.set_ylim([0, 1.2])
ax2.set_xlim([0, 40])

enter image description here

如果你想去掉顶部的x轴和右侧的y轴,有几种方法可以做到,建议你去找找以前的相关帖子。

最后,欢迎来到SO。

撰写回答