Traccia una linea morbida con PyPlot


112

Ho il seguente semplice script che traccia un grafico:

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

Così com'è ora, la linea va dritta da un punto all'altro, il che sembra ok, ma potrebbe essere migliore secondo me. Quello che voglio è smussare la linea tra i punti. In Gnuplot avrei tracciato con smooth cplines.

C'è un modo semplice per farlo in PyPlot? Ho trovato alcuni tutorial, ma sembrano tutti piuttosto complessi.

Risposte:


167

Potresti usare scipy.interpolate.splineper appianare i tuoi dati da solo:

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 è deprecato in scipy 0.19.0, usa invece la classe BSpline.

Il passaggio da splinea BSplinenon è un semplice copia / incolla e richiede un piccolo ritocco:

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

Prima: screenshot 1

Dopo: screenshot 2


2
Haha, non è stato difficile. Saluti! :) Solo una nota per gli altri che potrebbero cercare: ho dovuto importare scipy per usare linspace ().
Paul

Ops, scusa, avrei dovuto usarlo np.linspace. Corretto nella mia risposta.
Olivier Verdier

2
Il 300 è il numero di punti da fare tra T.min () e T.max (). Ho usato 1000 e sembra lo stesso. Prova con 5 però e vedrai una differenza.
CornSmith

2
splineè deprecato! spline è deprecato in scipy 0.19.0, usa invece la classe BSpline:from scipy.interpolate import BSpline
user890739

2
Questo non funzionerà se la T non è ordinata. E anche se la funzione (T) non è uno a uno.
Rahat Zaman

28

Per questo esempio la spline funziona bene, ma se la funzione non è intrinsecamente liscia e vuoi avere una versione smussata puoi anche provare:

from scipy.ndimage.filters import gaussian_filter1d

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

se aumenti il ​​sigma puoi ottenere una funzione più liscia.

Procedi con cautela con questo. Modifica i valori originali e potrebbe non essere quello che desideri.


10
Procedi con cautela con questo. Modifica i valori originali e potrebbe non essere quello che desideri.
tartaruga_casco_mole

8

Presumo tu intenda adattamento alla curva e non anti-aliasing dal contesto della tua domanda. PyPlot non ha alcun supporto integrato per questo, ma puoi facilmente implementare un po 'di adattamento della curva di base, come il codice visto qui , o se stai usando GuiQwt ha un modulo di adattamento della curva . (Probabilmente potresti anche rubare il codice da SciPy per farlo).


Grazie. Ho provato dieci diverse equazioni e [Usare le funzioni di base radiale per smussare / interpolare] [1] rbf = Rbf(x, y), fi = rbf(xi)era la migliore tra loro. [1]: scipy-cookbook.readthedocs.io/items/RadialBasisFunctions.html ,
Cloud Cho

1

Vedere la scipy.interpolatedocumentazione per alcuni esempi.

L'esempio seguente dimostra il suo utilizzo, per l'interpolazione spline lineare e cubica:

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

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.