python - cómo manejar una asíntota/discontinuidad con Matplotlib
numpy equation (3)
Al utilizar matrices enmascaradas , puede evitar trazar las regiones seleccionadas de una curva.
Para eliminar la singularidad en x = 2:
import matplotlib.numerix.ma as M # for older versions, prior to .98
#import numpy.ma as M # for newer versions of matplotlib
from pylab import *
figure()
xx = np.arange(-0.5,5.5,0.01)
vals = 1/(xx-2)
vals = M.array(vals)
mvals = M.masked_where(xx==2, vals)
subplot(121)
plot(xx, mvals, linewidth=3, color=''red'')
xlim(-1,6)
ylim(-5,5)
Esta simple curva podría ser un poco más clara sobre qué puntos están excluidos:
xx = np.arange(0,6,.2)
vals = M.array(xx)
mvals = M.masked_where(vals%2==0, vals)
subplot(122)
plot(xx, mvals, color=''b'', linewidth=3)
plot(xx, vals, ''rx'')
show()
Al trazar un gráfico con una discontinuidad / asíntota / singularidad / lo que sea, ¿hay alguna manera automática de evitar que Matplotlib ''junte los puntos'' a través del ''quiebre''? (ver código / imagen a continuación).
Leí que Sage tiene una instalación [detect_poles] que se veía bien, pero realmente quiero que funcione con Matplotlib.
import matplotlib.pyplot as plt
import numpy as np
from sympy import sympify, lambdify
from sympy.abc import x
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
xx = np.arange(-0.5,5.5,0.01)
# draw my curve
myfunction=sympify(1/(x-2))
mylambdifiedfunction=lambdify(x,myfunction,''numpy'')
ax.plot(xx, mylambdifiedfunction(xx),zorder=100,linewidth=3,color=''red'')
#set bounds
ax.set_xbound(-1,6)
ax.set_ybound(-4,4)
plt.show()
No, creo que no hay una forma incorporada de decirle a matplotlib
que ignore estos puntos. Después de todo, solo conecta puntos y no sabe nada sobre las funciones o lo que sucede entre los puntos.
Sin embargo, puede usar sympy
para buscar los polos, y luego parchear las piezas continuas de su función juntas. Aquí hay un código ciertamente feo que hace exactamente eso:
from pylab import *
from sympy import solve
from sympy.abc import x
from sympy.functions.elementary.complexes import im
xmin = -0.5
xmax = 5.5
xstep = 0.01
# solve for 1/f(x)=0 -- we will have poles there
discontinuities = sort(solve(1/(1/(x-2)),x))
# pieces from xmin to last discontinuity
last_b = xmin
for b in discontinuities:
# check that this discontinuity is inside our range, also make sure it''s real
if b<last_b or b>xmax or im(b):
continue
xi = np.arange(last_b, b, xstep)
plot(xi, 1./(xi-2),''r-'')
last_b = b
# from last discontinuity to xmax
xi = np.arange(last_b, xmax, xstep)
plot(xi, 1./(xi-2),''r-'')
xlim(xmin, xmax)
ylim(-4,4)
show()
Puede que esta no sea la solución elegante que está buscando, pero si solo quiere resultados en la mayoría de los casos, puede "recortar" valores grandes y pequeños de sus datos graficados a +∞
y -∞
respectivamente. Matplotlib no traza estos. Por supuesto, debe tener cuidado de no hacer que su resolución sea demasiado baja o su umbral de recorte demasiado alto.
utol = 100.
ltol = -100.
yy = 1/(xx-2)
yy[yy>utol] = np.inf
yy[yy<ltol] = -np.inf
ax.plot(xx, yy, zorder=100, linewidth=3, color=''red'')