Matplotlibで(f(x、y)= g(x、y)の形式の暗黙の方程式(例:X ^ y = y ^ x))をプロットしたいと思います。これは可能ですか?
6 に答える
これに対するサポートはあまり良くないと思いますが、次のようなものを試すことができます
import matplotlib.pyplot
from numpy import arange
from numpy import meshgrid
delta = 0.025
xrange = arange(-5.0, 20.0, delta)
yrange = arange(-5.0, 20.0, delta)
X, Y = meshgrid(xrange,yrange)
# F is one side of the equation, G is the other
F = Y**X
G = X**Y
matplotlib.pyplot.contour(X, Y, (F - G), [0])
matplotlib.pyplot.show()
APIドキュメントを参照してくださいcontour
:4番目の引数がシーケンスの場合、プロットする等高線を指定します。しかし、プロットはあなたの範囲の解像度と同じくらい良いでしょう、そしてそれが決して正しくないかもしれない特定の特徴があります、しばしば自己交差点で。
この質問にsympyのタグを付けたので、そのような例を示します。
ドキュメントから:http://docs.sympy.org/latest/modules/plotting.html。
from sympy import var, plot_implicit
var('x y')
plot_implicit(x*y**3 - y*x**3)
matplotlibは方程式をプロットしません。一連のポイントをプロットします。のようなツールを使用してscipy.optimize
、暗黙の方程式のx値からyポイントを数値的に計算する(またはその逆)か、必要に応じて他の任意の数のツールを使用できます。
たとえばx ** 2 + x * y + y ** 2 = 10
、特定の領域で陰方程式をプロットする例を次に示します。
from functools import partial
import numpy
import scipy.optimize
import matplotlib.pyplot as pp
def z(x, y):
return x ** 2 + x * y + y ** 2 - 10
x_window = 0, 5
y_window = 0, 5
xs = []
ys = []
for x in numpy.linspace(*x_window, num=200):
try:
# A more efficient technique would use the last-found-y-value as a
# starting point
y = scipy.optimize.brentq(partial(z, x), *y_window)
except ValueError:
# Should we not be able to find a solution in this window.
pass
else:
xs.append(x)
ys.append(y)
pp.plot(xs, ys)
pp.xlim(*x_window)
pp.ylim(*y_window)
pp.show()
sympyには暗黙の方程式(および不等式)プロッターがあります。これはGSoCの一部として作成され、matplotlibフィギュアインスタンスとしてプロットを生成します。
http://docs.sympy.org/latest/modules/plotting.html#sympy.plotting.plot_implicit.plot_implicitのドキュメント
sympyバージョン0.7.2以降、次のように利用できます。
>>> from sympy.plotting import plot_implicit
>>> p = plot_implicit(x < sin(x)) # also creates a window with the plot
>>> the_matplotlib_axes_instance = p._backend._ax
編集:plt.plot()を使用して双曲線をプロットすると、望ましくない分岐効果が得られます。その場所のplt.scatter()は引き続き機能するはずです。その場合、負または正の値の順序を逆にする必要はありませんが、何らかの理由で(scipyからの等高線図を使用する代わりに)このコードを使用したい場合は、plt.scatter()でとにかく機能します
一般に、2次元の陰関数は、次のように記述できます。
f(x、y)= 0
これをf(x)= yと書くことはできないため、簡単にプログラム可能な離散xのセットからyを計算することはできません。ただし、グリッドから生成されたポイントが実際の関数からどれだけ近いかを確認することは可能です。
したがって、xとyのグリッドをカスタムポイント密度に作成し、各ポイントが方程式を満たすのにどれだけ近いかを確認します。
言い換えると、f(x、y)= 0を取得できない場合は、おそらく0に近づけることができます。f(x、y)= 0を探す代わりに、f(x、y)>-\を探します。イプシロンおよびf(x、y)<\epsilon。
\ epsilonは許容誤差であり、この条件が許容誤差0の範囲内に収まり、グリッドを適切に調整すると、関数をプロットできます。
以下のコードは、半径1の円(f(x、y)= x ^ 2 + y ^ 2 -1 = 0)に対してそれを実行します。\epsilonには記号drを使用しました。
また、plt.plot関数が線を正しい順序で接続していることを確認するために、負のy値に対してx値の逆バージョンを使用します。このように、f(x、y)の評価は時計回りのループで行われるため、最も近い値が次々になります。これがないと、関数の反対側からの線が接続され、わずかに塗りつぶされたように見えます。
import numpy as np
import matplotlib.pyplot as plt
r = 1 #arbitrary radius to set up the span of points
points = 250
dr = r/points #epsilon window
x=list(np.linspace(-5*r,5*r,5*points+1)) #setting up the x,y grid
y=x
xreversed = reversed(x) #reversing the array
x_0=[] #placeholder arrays
y_0=[]
for i in x:
for j in y:
if i**2 + j**2 -1 < dr and i**2+j**2 -1 > -dr and j >= 0: #positive values of y
x_0.append(i)
y_0.append(j)
for i in xreversed:
for j in y:
if i**2+j**2 -1 < dr and i**2+j**2 -1 > -dr and j < 0: #negative values of y, using x reversed
x_0.append(i)
y_0.append(j)
plt.plot(x_0,y_0)
plt.show()
スティーブ、マイク、アレックスに感謝します。私はスティーブの解決策に賛成しました(以下のコードを参照してください)。私の唯一の残りの問題は、zorderで前面に強制できる通常のプロットとは対照的に、等高線プロットがグリッド線の後ろに表示されることです。これ以上の半分は大歓迎です。
乾杯、ゲデス
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, FormatStrFormatter
import numpy as np
fig = plt.figure(1)
ax = fig.add_subplot(111)
# set up axis
ax.spines['left'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
# setup x and y ranges and precision
x = np.arange(-0.5,5.5,0.01)
y = np.arange(-0.5,5.5,0.01)
# draw a curve
line, = ax.plot(x, x**2,zorder=100)
# draw a contour
X,Y=np.meshgrid(x,y)
F=X**Y
G=Y**X
ax.contour(X,Y,(F-G),[0],zorder=100)
#set bounds
ax.set_xbound(-1,7)
ax.set_ybound(-1,7)
#produce gridlines of different colors/widths
ax.xaxis.set_minor_locator(MultipleLocator(0.2))
ax.yaxis.set_minor_locator(MultipleLocator(0.2))
ax.xaxis.grid(True,'minor',linestyle='-')
ax.yaxis.grid(True,'minor',linestyle='-')
minor_grid_lines = [tick.gridline for tick in ax.xaxis.get_minor_ticks()]
for idx,loc in enumerate(ax.xaxis.get_minorticklocs()):
if loc % 2.0 == 0:
minor_grid_lines[idx].set_color('0.3')
minor_grid_lines[idx].set_linewidth(2)
elif loc % 1.0 == 0:
minor_grid_lines[idx].set_c('0.5')
minor_grid_lines[idx].set_linewidth(1)
else:
minor_grid_lines[idx].set_c('0.7')
minor_grid_lines[idx].set_linewidth(1)
minor_grid_lines = [tick.gridline for tick in ax.yaxis.get_minor_ticks()]
for idx,loc in enumerate(ax.yaxis.get_minorticklocs()):
if loc % 2.0 == 0:
minor_grid_lines[idx].set_color('0.3')
minor_grid_lines[idx].set_linewidth(2)
elif loc % 1.0 == 0:
minor_grid_lines[idx].set_c('0.5')
minor_grid_lines[idx].set_linewidth(1)
else:
minor_grid_lines[idx].set_c('0.7')
minor_grid_lines[idx].set_linewidth(1)
plt.show()