Matplotlib fill_between边缘效果与`where`参数

时间:2013-10-06 21:39:39

标签: matplotlib

我想绘制具有不同颜色的两条曲线之间的区域,无论其中一条线是正还是负。当曲线改变符号时,我得到边缘效应,区域不连续着色。设置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()

enter image description here http://i.stack.imgur.com/9Q9Ff.png

**编辑**基于pyHazard的答案正确解决了上述问题,但我仍遇到困难:

修订案例(参见代码) - 如果两条求和曲线具有相同的符号,则需要填充两条求和曲线之间的区域,并且在其中一条曲线和零其他曲线之间填充。 where=条件发生变化时,填充区域必须是连续的。包括微小的边际确实有帮助,但并不能完全解决问题(填充表面仍然中断)。我需要的是fill_between其中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()

fill_between_2

为了更清楚,这是原始图(上面的代码中带有eta=0.)。那里的一切都很好,除了绿色和红色区域的垂直中断。正弦曲线和零之间的空白区域很好。有问题的垂直中断来自填充区域的定义:如果它们具有相同的符号,则在正弦和水平曲线之间,或者如果正弦和水平曲线具有相反的符号,则在水平曲线和零之间。因此填充区域的条件有一个转换,空白的垂直区域是不希望的边缘效应......

fill_between_3

*最终编辑* [与解决方案]

因为我无法在fill_between中找到解决方案,所以一个解决方案(基于pyHazard的答案)是重新计算填充区域的上限和下限,以确保它们连续(在{{中不再开关) 1}}条件)。

fill_between

fill_between_4

1 个答案:

答案 0 :(得分:3)

只要您只关注一行或另一行,我建议您查看您的比较。以下产生了更令人愉悦的情节。 (注意,绘图样式已更改,以使数据点清晰。)

如果您希望负面的所有AREA都是红色且正面为绿色,则需要在轴上添加额外的数据点。

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

eta=1e-6
y1positive=(y1+eta)>=0
y1negative=(y1-eta)<=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,interpolate=False)
plt.fill_between(x,y2,y1,where=y1negative,color='red',alpha=0.5,interpolate=False)
plt.legend()
plt.show()

enter image description here

**编辑**我还不能发表评论,所以我将其添加到编辑中。我是论坛界的新手,所以我不确定这是否算是礼仪。

我不确定我是否了解修订后的情况。你只是想用红色和绿色填充白色区域吗?如果是这样,你可能不需要额外的条件,只需要以最简单的方式填充,如下所示。

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)

y21 = numpy.amax(numpy.vstack((y2,y2+y1)), axis=0)
y31 = numpy.amin(numpy.vstack((y3,y3+y1)), axis=0)

plt.plot(x,x*0,'--k')
plt.fill_between(x,y21,y1,color='green',alpha=0.5,linewidth=0)
plt.fill_between(x,y31,y1,color='red',alpha=0.5,linewidth=0) 

plt.show()

enter image description here