0

線の 1 つが正か負かに関係なく、2 つの曲線の間の領域を異なる色でプロットしたいと考えています。曲線の符号が変わると、領域の不連続な色付けでエッジ効果が得られました。設定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の回答に基づいていますが、それでも問題が発生します:

改訂されたケース (コードを参照) - 2 つの合計された曲線が同じ符号を持っている場合はそれらの間の領域を埋める必要があり、そうでない場合はそれらの 1 つとゼロの間の領域を埋める必要があります。where=条件が変化した場合、塗りつぶされた領域は連続している必要があります。小さなマージンを含めることは確かに役立ちますが、問題を完全に解決するわけではありません (塗りつぶされたサーフェスはまだ中断されています)。必要なのは、実際には、幅のない条件であるfill_betweenwherey1=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.上記のコードを使用)。緑と赤の領域の垂直方向の中断を除いて、すべて問題ありません。正弦曲線とゼロの間の空白領域は問題ありません。問題のある垂直方向の中断は、塗りつぶされた領域の定義に起因します。サインと水平曲線が同じ符号を持っている場合、または水平曲線とゼロの間で、サインと水平曲線が反対の符号を持っている場合です。そのため、塗りつぶされた領域の条件にスイッチがあり、空白の垂直ゾーンは望ましくないエッジ効果です...

塗りつぶし_間_3

*最終編集* [ソリューション付き]

内で解決策を見つけることができないためfill_between、1 つの解決策 (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

いずれかの行のみに関心がある限り、比較を検討することをお勧めします。以下は、より楽しいプロットを生成します。(データ ポイントを明確にするためにプロット スタイルが変更されていることに注意してください。)

負の側のすべての 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()

ここに画像の説明を入力

** 編集 ** まだコメントできないので、これを編集に追加します。私はフォーラム シーンに慣れていないので、これが適切なエチケットと見なされるかどうかはわかりません。

改訂された状況を理解しているかどうかわかりません。白い部分を赤と緑で埋めようとしているだけですか?もしそうなら、あなたはおそらく余分な条件を必要とせず、以下に示すように最も簡単な方法でそれらの間を埋める必要があります.

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 に答える