Tracer une ligne lisse avec PyPlot

112

J'ai le script simple suivant qui trace un graphique:

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

Comme c'est le cas maintenant, la ligne va directement d'un point à l'autre, ce qui semble correct, mais pourrait être mieux à mon avis. Ce que je veux, c'est lisser la ligne entre les points. Dans Gnuplot, j'aurais tracé avec smooth cplines.

Existe-t-il un moyen simple de le faire dans PyPlot? J'ai trouvé des tutoriels, mais ils semblent tous assez complexes.

Paul
la source

Réponses:

167

Vous pouvez utiliser scipy.interpolate.splinepour lisser vos données vous-même:

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 obsolète dans scipy 0.19.0, utilisez plutôt la classe BSpline.

Passer de splineà BSplinen'est pas un simple copier / coller et nécessite quelques ajustements:

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

Avant: capture d'écran 1

Après: capture d'écran 2

Olivier Verdier
la source
2
Haha, ce n'était pas difficile. À votre santé! :) Juste une note pour les autres qui pourraient chercher: j'ai dû importer scipy pour utiliser linspace ().
Paul
Oups, désolé, aurait dû être utilisé np.linspace. Corrigé dans ma réponse.
Olivier Verdier
2
Le 300 est le nombre de points à faire entre T.min () et T.max (). J'ai utilisé 1000 et ça a la même apparence. Essayez avec 5 et vous verrez une différence.
CornSmith
2
splineest obsolète! spline est obsolète dans scipy 0.19.0, utilisez la classe BSpline à la place:from scipy.interpolate import BSpline
user890739
2
Cela ne fonctionnera pas si le T n'est pas trié. Et aussi si la fonction (T) n'est pas un-à-un.
Rahat Zaman
28

Pour cet exemple, la spline fonctionne bien, mais si la fonction n'est pas intrinsèquement lisse et que vous voulez avoir une version lissée, vous pouvez également essayer:

from scipy.ndimage.filters import gaussian_filter1d

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

si vous augmentez sigma, vous pouvez obtenir une fonction plus lissée.

Procédez avec prudence avec celui-ci. Il modifie les valeurs d'origine et peut ne pas être ce que vous voulez.

Sajad Norouzi
la source
10
Procédez avec prudence avec celui-ci. Il modifie les valeurs d'origine et peut ne pas être ce que vous voulez.
tartaruga_casco_mole
8

Je suppose que vous parlez d' ajustement de courbe et non d' anti-crénelage dans le contexte de votre question. PyPlot n'a pas de support intégré pour cela, mais vous pouvez facilement implémenter vous-même un ajustement de courbe de base, comme le code vu ici , ou si vous utilisez GuiQwt, il dispose d'un module d' ajustement de courbe . (Vous pourriez probablement également voler le code de SciPy pour le faire également).

Nick Bastin
la source
Merci. J'ai essayé dix équations différentes et [Utiliser les fonctions de base radiale pour le lissage / interpolation] [1] rbf = Rbf(x, y), fi = rbf(xi)était le meilleur parmi eux. [1]: scipy-cookbook.readthedocs.io/items/RadialBasisFunctions.html ,
Cloud Cho
1

Consultez la scipy.interpolatedocumentation pour quelques exemples.

L'exemple suivant montre son utilisation, pour l'interpolation spline linéaire et cubique:

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

entrez la description de l'image ici

Mateen Ulhaq
la source