Matplotlib fill_between edge effect with `where` argument -
i want plot region between 2 curves different colors whether 1 of line positive or negative. got edge effect non-continuous coloring of region when curve changes of sign. setting interpolate=true
not help. edge effect related resolution (voluntarily coarse in basic example below) - enhancing not want. better solution make smooth transitions? thanks.
import matplotlib.pyplot 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
** edit ** based on pyhazard's answer addressing problem above, still encounter difficulties:
revised case (see code) - need fill area between 2 summed curves if have same sign, , between 1 of them , 0 otherwize. filled area must continuous when where=
condition changes. including tiny margin indeed helps, not totally resolve problem (filled surface still interrupted). needed there fill_between
y1=0
, condition no width... need kind of condition where y1-eta<=0<=y1+eta
foolishly blocked there now. idea make filled area totally continuous? thanks!
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()
to make clearer, here original plot (with eta=0.
in code above). fine there, except vertical interruptions in green , red areas. blank areas between sine curve , 0 fine. problematic vertical interruptions come definition of filled areas: between sine , horizontal curve if have same sign, or between horizontal curve , 0 if sine , horizontal curve have opposite signs. there switch in conditions filled areas, blank vertical zones undesirable edge effects...
* final edit * [with solution]
because cannot find solution within fill_between
, 1 solution (based on pyhazard's answer) recalculate upper , lower limit of filled areas make sure have them continuous (no more swith in fill_between
condition).
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 upper , lower limit of filled areas # have each of them 1 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()
as long concerned 1 line or other suggest looking @ comparison. following produces more pleasing plot. (note plotting style changed make data points clear.)
if had intended of area on negative side red , positive side green need add additional data-points series that lie on axis.
import matplotlib.pyplot 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()
** edit ** cannot yet comment i'm adding edit. i'm new forum scene i'm not sure if considered proper etiquette.
i'm not sure understand revised situation. trying fill white areas in red , green? if don't need conditionals , need to fill between in simplest way shown below.
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()
Comments
Post a Comment