我想绘制两条不同颜色的曲线之间的区域,无论其中一条线是正还是负。当符号的曲线变化时,我得到了区域不连续着色的边缘效应。设置interpolate=True
并没有真正帮助。边缘效果与分辨率有关(在下面的基本示例中自愿粗略) - 增强它并不是我真正想要的。有更好的解决方案来实现平滑过渡吗?谢谢。
import matplotlib.pyplot as plt
import numpy
plt.figure()
x=numpy.arange(0.,1.05,0.05)
y1=numpy.sin(2*numpy.pi*x)
y2=y1+0.2
y1positive=y1>0
y1negative=y1<=0
plt.plot(x,y1,'r',label='y1')
plt.plot(x,y2,'g',label='y2')
plt.plot(x,x*0,'--k')
plt.fill_between(x,y2,y1,where=y1positive,color='green',alpha=0.5)
plt.fill_between(x,y2,y1,where=y1negative,color='red',alpha=0.5,interpolate=True)
plt.legend()
http://i.stack.imgur.com/9Q9Ff.png
** 编辑 ** 基于 pyHazard 的回答,正确解决了上述问题,但我仍然遇到困难:
修改后的情况(见代码) - 如果两条求和曲线之间的区域具有相同的符号,我需要填充它们之间的区域,并且在其中一条曲线和零之间。当where=
条件发生变化时,填充区域必须是连续的。包括一个微小的边距确实有帮助,但并不能完全解决问题(填充表面仍然中断)。真正需要的是fill_between
where y1=0
,这是一个没有宽度的条件......然后我只需要一种条件where y1-eta<=0<=y1+eta
,但我现在愚蠢地被阻止了。有什么想法可以使填充区域完全连续吗?谢谢!
plt.figure()
x=numpy.arange(0.,3.05,0.05)
y1=numpy.sin(2*numpy.pi*x)
y2=[2.]*len(y1)
y3=[-2.]*len(y1)
eta=1e-6
y1positive=y1+eta>=0
y1negative=y1-eta<=0
plt.plot(x,x*0,'--k')
plt.plot(x,y1,'.-k',label='y1')
plt.plot(x,y2,'.-g',label='y2')
plt.plot(x,y3,'.-r',label='y3')
plt.fill_between(x,y2+y1,y1,where=y1positive,color='green',alpha=0.5,linewidth=0)
plt.fill_between(x,y2,0,where=y1negative,color='green',alpha=0.5,linewidth=0)
plt.fill_between(x,y3+y1,y1,where=y1negative,color='red',alpha=0.5,linewidth=0)
plt.fill_between(x,y3,0,where=y1positive,color='red',alpha=0.5,linewidth=0)
plt.legend()
为了更清楚,这是原始图(eta=0.
在上面的代码中)。那里一切都很好,除了绿色和红色区域的垂直中断。正弦曲线和零之间的空白区域很好。有问题的垂直中断来自填充区域的定义:如果它们具有相同的符号,则在正弦和水平曲线之间,或者如果正弦和水平曲线具有相反的符号,则在水平曲线和零之间。所以填充区域的条件有一个切换,空白垂直区域是不希望的边缘效果......
*最终编辑* [有解决方案]
因为我无法在 内找到解决方案fill_between
,所以一种解决方案(基于 pyHazard 的回答)是重新计算填充区域的上限和下限,以确保它们连续(不再fill_between
有条件切换)。
plt.figure()
x=numpy.arange(0.,3.05,0.05)
y1=numpy.sin(2*numpy.pi*x)
y2=[2.]*len(y1)
y3=[-2.]*len(y1)
y1positive=y1>=0
y1negative=y1<=0
plt.plot(x,x*0,'--k')
plt.plot(x,y1,'.-k',label='y1')
plt.plot(x,y2,'.-g',label='y2')
plt.plot(x,y3,'.-r',label='y3')
#Solution: recalculate the upper and lower limit of filled areas
# to have each of them as one continuous line
y0=[0.]*len(y1)
y1pos=numpy.amax(numpy.vstack((y1,y0)),axis=0.)
y1neg=numpy.amin(numpy.vstack((y1,y0)),axis=0.)
y21=y2+y1pos
y31=y3+y1neg
plt.fill_between(x,y21,y1pos,color='green',alpha=0.5,linewidth=0)
plt.fill_between(x,y31,y1neg,color='red',alpha=0.5,linewidth=0)
plt.legend()