2010-03-20 26 views

Respuesta

18

no creo que hay un apoyo muy bueno para esto, pero usted podría intentar algo así como

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

Ver el API docs para contour: si el cuarto argumento es una secuencia a continuación, se especifica que las curvas de nivel para trazar . Pero la trama solo será tan buena como la resolución de tus rangos, y hay ciertas características que pueden no ser correctas, a menudo en los puntos de autointersección.

+0

Esta es una buena solución. Mi solución es una forma más manual de obtener la misma información utilizando el mismo concepto subyacente: configurar la ecuación implícita como f (x, y) tal que f (x, y) = 0 es equivalente a la ecuación implícita original y aislando su contorno cero. –

6

matplotlib no grafica ecuaciones; traza series de puntos. Puede usar una herramienta como scipy​.optimize para calcular numéricamente los puntos y desde x valores (o viceversa) de ecuaciones implícitas numéricamente o cualquier cantidad de otras herramientas según corresponda.


Por ejemplo, aquí se muestra un ejemplo en el que trazar la ecuación implícita x ** 2 + x * y + y ** 2 = 10 en una determinada región.

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

Muchos gracias Steve, Mike, Alex. He seguido la solución de Steve (ver el código a continuación). Mi único problema restante es que la trama de contorno aparece detrás de mis líneas de cuadrícula, a diferencia de una trama regular, que puedo forzar al frente con zorder. Cualquier halp más apreciado.

Saludos, Geddes

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

@Geddes, parece que el soporte para el contorno con respecto a zorder se ha agregado recientemente a la fuente matplotlib. Desde su tronco SVN: http://matplotlib.svn.sourceforge.net/viewvc/matplotlib?view = rev & revision = 8098 – Mark

14

Puesto que usted ha etiquetado a esta pregunta con sympy, voy a dar un ejemplo.

De la documentación: http://docs.sympy.org/modules/plotting.html.

from sympy import var, Plot 
var('x y') 
Plot(x*y**3 - y*x**3) 
+1

Parece que la nueva sintaxis es 'plot_implicit (Eq (x ** 5 + y ** 5, 1))', y el nuevo enlace de documento [está aquí] (http: //docs.sympy .org/latest/modules/plotting.html). –

4

Hay un trazador de ecuación implícita (y desigualdad) en sympy. Se crea como parte de GSoC y produce las representaciones como instancias de figuras matplotlib.

Docs en http://docs.sympy.org/latest/modules/plotting.html#sympy.plotting.plot_implicit.plot_implicit

Desde la versión 0.7.2 sympy está disponible como:

>>> 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 
+0

Parece que se lanzó ahora. :) –

+0

¿De dónde viene tu 'the_matplotlib_axes_instance'? – theV0ID

+0

'p' es la trama que ha creado. 'p._backend._ax' sería una instancia de ejes y, si lo desea, puede hacer referencia a ella en una nueva variable y usarla para lo que sea que use cualquier instancia de hachas matplotlib. – Krastanov

Cuestiones relacionadas