Ділянка рівна лінія з PyPlot


112

У мене є такий простий сценарій, який малює графік:

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

Як і зараз, лінія йде прямо від точки до точки, яка виглядає нормально, але могла бути кращою на мою думку. Те, що я хочу, - це згладити лінію між точками. У Гнуплоті я б задумався smooth cplines.

Чи є простий спосіб зробити це в PyPlot? Я знайшов кілька навчальних посібників, але всі вони здаються досить складними.

Відповіді:


167

Ви можете scipy.interpolate.splineсамостійно згладити свої дані:

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 застарілий у scipy 0.19.0, використовуйте натомість клас BSpline.

Перехід з режиму splineдо BSplineне є простою копією / вставкою і потребує невеликої настройки:

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

Перед: скріншот 1

Після: скріншот 2


2
Ха-ха, це було не складно. Ура! :) Лише зауваження для інших, що може виглядати: мені довелося імпортувати scipy, щоб використовувати linspace ().
Павло

Ой, вибачте, мав би використати np.linspace. Виправлено мою відповідь.
Олів'є Верд'є

2
Колекція 300 - це скільки балів зробити між T.min () та T.max (). Я використав 1000, і це виглядає так само. Спробуйте з 5, хоча ви побачите різницю.
CornSmith

2
splineзастаріло! spline застарілий у scipy 0.19.0, використовуйте натомість клас BSpline:from scipy.interpolate import BSpline
user890739

2
Це не спрацює, якщо Т не відсортовано. А також якщо функтитон (T) не один на один.
Рахат Заман

28

У цьому прикладі сплайн працює добре, але якщо функція не є гладкою, і ви хочете мати згладжену версію, ви також можете спробувати:

from scipy.ndimage.filters import gaussian_filter1d

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

якщо збільшити сигму, ви можете отримати більш плавну функцію.

Дійте обережно з цим. Він змінює вихідні значення і може бути не тим, що потрібно.


10
Дійте обережно з цим. Він змінює вихідні значення і може бути не тим, що потрібно.
tartaruga_casco_mole

8

Я припускаю, що ви маєте на увазі підгонку кривих, а не антизшивання з контексту вашого питання. PyPlot не має вбудованої підтримки для цього, але ви можете легко реалізувати деякі базові криві самостійно, як код, який ви бачите тут , або якщо ви використовуєте GuiQwt, він має модуль підгонки кривої . (Ви можете, ймовірно, також вкрасти код у SciPy, щоб це зробити).


Дякую. Я спробував десять різних рівнянь і [Використання радіальних базових функцій для згладжування / інтерполяції] [1] rbf = Rbf(x, y), fi = rbf(xi)було найкращим серед них. [1]: scipy-cookbook.readthedocs.io/items/RadialBasisFunctions.html ,
Хмара Чо

1

Дивіться scipy.interpolateдокументацію для деяких прикладів.

Наступний приклад демонструє його використання для лінійної та кубічної сплайнованої інтерполяції:

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

введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.