0

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

填充之间_2

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

fill_between_3

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

因为我无法在 内找到解决方案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()

fill_between_4

4

1 回答 1

4

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

如果您希望负侧的所有区域都为红色,正侧为绿色,您将需要向位于轴上的系列添加额外的数据点。

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()

在此处输入图像描述

** 编辑 ** 我还不能发表评论,所以我将其添加到编辑中。我是论坛场景的新手,所以我不确定这是否被认为是适当的礼仪。

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

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()

在此处输入图像描述

于 2013-10-06T23:30:05.420 回答