Trazar una línea suave con PyPlot

112

Tengo el siguiente script simple que traza un gráfico:

import matplotlib.pyplot as plt
import numpy as np

T = np.array([6, 7, 8, 9, 10, 11, 12])
power = np.array([1.53E+03, 5.92E+02, 2.04E+02, 7.24E+01, 2.72E+01, 1.10E+01, 4.70E+00])

plt.plot(T,power)
plt.show()

Como está ahora, la línea va directamente de un punto a otro, lo que se ve bien, pero podría ser mejor en mi opinión. Lo que quiero es suavizar la línea entre los puntos. En Gnuplot habría conspirado smooth cplines.

¿Existe una manera fácil de hacer esto en PyPlot? Encontré algunos tutoriales, pero todos parecen bastante complejos.

Pablo
fuente

Respuestas:

167

Puede utilizar scipy.interpolate.splinepara suavizar sus datos usted mismo:

from scipy.interpolate import spline

# 300 represents number of points to make between T.min and T.max
xnew = np.linspace(T.min(), T.max(), 300)  

power_smooth = spline(T, power, xnew)

plt.plot(xnew,power_smooth)
plt.show()

spline está obsoleto en scipy 0.19.0, use la clase BSpline en su lugar.

Cambiar de splinea BSplineno es una tarea sencilla de copiar / pegar y requiere algunos ajustes:

from scipy.interpolate import make_interp_spline, BSpline

# 300 represents number of points to make between T.min and T.max
xnew = np.linspace(T.min(), T.max(), 300) 

spl = make_interp_spline(T, power, k=3)  # type: BSpline
power_smooth = spl(xnew)

plt.plot(xnew, power_smooth)
plt.show()

Antes de: captura de pantalla 1

Después: captura de pantalla 2

Olivier Verdier
fuente
2
Jaja, eso no fue difícil. ¡Salud! :) Solo una nota para otros que podrían estar buscando: tuve que importar scipy para usar linspace ().
Paul
Vaya, lo siento, debería haber usado np.linspace. Corregido en mi respuesta.
Olivier Verdier
2
El 300 es la cantidad de puntos que hay que marcar entre T.min () y T.max (). Usé 1000 y se ve igual. Sin embargo, pruebe con 5 y verá la diferencia.
CornSmith
2
spline¡es obsoleto! spline está en desuso en scipy 0.19.0, use la clase BSpline en su lugar:from scipy.interpolate import BSpline
user890739
2
Esto no funcionará si la T no está ordenada. Y también si la función (T) no es uno a uno.
Rahat Zaman
28

Para este ejemplo, el spline funciona bien, pero si la función no es inherentemente suave y desea tener una versión suavizada, también puede probar:

from scipy.ndimage.filters import gaussian_filter1d

ysmoothed = gaussian_filter1d(y, sigma=2)
plt.plot(x, ysmoothed)
plt.show()

si aumenta sigma, puede obtener una función más suavizada.

Proceda con precaución con este. Modifica los valores originales y puede que no sea lo que desea.

Sajad Norouzi
fuente
10
Proceda con precaución con este. Modifica los valores originales y puede que no sea lo que desea.
tartaruga_casco_mole
8

Supongo que te refieres al ajuste de curvas y no al suavizado del contexto de tu pregunta. PyPlot no tiene soporte incorporado para esto, pero puede implementar fácilmente algunos ajustes de curvas básicos usted mismo, como el código que se ve aquí , o si está usando GuiQwt, tiene un módulo de ajuste de curvas . (Probablemente también podría robar el código de SciPy para hacer esto también).

Nick Bastin
fuente
Gracias. Probé diez ecuaciones diferentes y [Usar funciones de base radial para suavizar / interpolar] [1] rbf = Rbf(x, y), fi = rbf(xi)fue la mejor entre ellas. [1]: scipy-cookbook.readthedocs.io/items/RadialBasisFunctions.html ,
Cloud Cho
1

Consulte la scipy.interpolatedocumentación para ver algunos ejemplos.

El siguiente ejemplo demuestra su uso para la interpolación spline lineal y cúbica:

>>> from scipy.interpolate import interp1d

>>> x = np.linspace(0, 10, num=11, endpoint=True)
>>> y = np.cos(-x**2/9.0)
>>> f = interp1d(x, y)
>>> f2 = interp1d(x, y, kind='cubic')

>>> xnew = np.linspace(0, 10, num=41, endpoint=True)
>>> import matplotlib.pyplot as plt
>>> plt.plot(x, y, 'o', xnew, f(xnew), '-', xnew, f2(xnew), '--')
>>> plt.legend(['data', 'linear', 'cubic'], loc='best')
>>> plt.show()

ingrese la descripción de la imagen aquí

Mateen Ulhaq
fuente