Zeichnen Sie eine glatte Linie mit PyPlot

111

Ich habe das folgende einfache Skript, das ein Diagramm darstellt:

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

So wie es jetzt ist, geht die Linie direkt von Punkt zu Punkt, was in Ordnung aussieht, aber meiner Meinung nach besser sein könnte. Ich möchte die Linie zwischen den Punkten glätten. In Gnuplot hätte ich mit geplottet smooth cplines.

Gibt es eine einfache Möglichkeit, dies in PyPlot zu tun? Ich habe einige Tutorials gefunden, aber alle scheinen ziemlich komplex zu sein.

Paul
quelle

Antworten:

166

Sie können scipy.interpolate.splineIhre Daten selbst glätten:

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 ist in Scipy 0.19.0 veraltet. Verwenden Sie stattdessen die BSpline-Klasse.

Das Wechseln von splinezu BSplineist kein einfaches Kopieren / Einfügen und erfordert einige Anpassungen:

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

Vor: Screenshot 1

Nach dem: Screenshot 2

Olivier Verdier
quelle
2
Haha, das war nicht schwer. Prost! :) Nur ein Hinweis für andere, die vielleicht suchen: Ich musste scipy importieren, um linspace () zu verwenden.
Paul
Ups, sorry, hätte verwenden sollen np.linspace. In meiner Antwort korrigiert.
Olivier Verdier
2
Die 300 gibt an, wie viele Punkte zwischen T.min () und T.max () zu machen sind. Ich habe 1000 verwendet und es sieht genauso aus. Versuchen Sie es mit 5 und Sie werden einen Unterschied sehen.
CornSmith
2
splineist veraltet! Spline ist in scipy 0.19.0 veraltet, verwenden Sie stattdessen die BSpline-Klasse:from scipy.interpolate import BSpline
user890739
2
Dies funktioniert nicht, wenn das T nicht sortiert ist. Und auch wenn die Funktion (T) nicht eins zu eins ist.
Rahat Zaman
28

In diesem Beispiel funktioniert Spline gut, aber wenn die Funktion von Natur aus nicht glatt ist und Sie eine geglättete Version wünschen, können Sie auch Folgendes versuchen:

from scipy.ndimage.filters import gaussian_filter1d

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

Wenn Sie Sigma erhöhen, können Sie eine geglättete Funktion erhalten.

Gehen Sie mit diesem vorsichtig vor. Es ändert die ursprünglichen Werte und entspricht möglicherweise nicht Ihren Wünschen.

Sajad Norouzi
quelle
10
Gehen Sie mit diesem vorsichtig vor. Es ändert die ursprünglichen Werte und entspricht möglicherweise nicht Ihren Wünschen.
tartaruga_casco_mole
8

Ich nehme an, Sie meinen Kurvenanpassung und nicht Anti-Aliasing aus dem Kontext Ihrer Frage. PyPlot hat keine eingebaute Unterstützung für diese, aber Sie können einige grundlegende Kurvenanpassung sich leicht implementieren, wie der Code gesehen hier , oder wenn Sie mit GuiQwt eine Kurvenanpassung hat Modul . (Sie könnten wahrscheinlich auch den Code von SciPy stehlen , um dies zu tun).

Nick Bastin
quelle
Vielen Dank. Ich habe zehn verschiedene Gleichungen ausprobiert und [Radiale Basisfunktionen zum Glätten / Interpolieren verwenden] [1] rbf = Rbf(x, y), fi = rbf(xi)war am besten unter ihnen. [1]: scipy-cookbook.readthedocs.io/items/RadialBasisFunctions.html ,
Cloud Cho
1

In der scipy.interpolateDokumentation finden Sie einige Beispiele.

Das folgende Beispiel zeigt die Verwendung für die lineare und kubische Spline-Interpolation:

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

Geben Sie hier die Bildbeschreibung ein

Mateen Ulhaq
quelle