Trace uma linha suave com PyPlot


112

Eu tenho o seguinte script simples que traça um 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()

Do jeito que está agora, a linha vai direto de um ponto a outro, o que parece bom, mas poderia ser melhor na minha opinião. O que eu quero é suavizar a linha entre os pontos. No Gnuplot, eu teria planejado smooth cplines.

Existe uma maneira fácil de fazer isso no PyPlot? Encontrei alguns tutoriais, mas todos parecem bastante complexos.

Respostas:


167

Você pode usar scipy.interpolate.splinepara suavizar seus dados sozinho:

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 no scipy 0.19.0; em vez disso, use a classe BSpline.

Mudar de splinepara BSplinenão é uma tarefa simples de copiar / colar e requer alguns 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: captura de tela 1

Depois de: captura de tela 2


2
Haha, isso não foi difícil. Felicidades! :) Apenas uma nota para outros que possam estar procurando: Tive que importar o scipy para usar o linspace ().
Paul,

Opa, desculpe, deveria ter usado np.linspace. Corrigido em minha resposta.
Olivier Verdier

2
O 300 é quantos pontos fazer entre T.min () e T.max (). Usei 1000 e parece o mesmo. Experimente com 5 e você verá a diferença.
CornSmith de

2
splineestá obsoleto! spline está obsoleto no scipy 0.19.0, use a classe BSpline em vez disso:from scipy.interpolate import BSpline
user890739

2
Isso não funcionará se o T não estiver classificado. E também se a função (T) não for um-para-um.
Rahat Zaman

28

Para este exemplo, o spline funciona bem, mas se a função não é inerentemente suave e você deseja ter uma versão suavizada, você também pode tentar:

from scipy.ndimage.filters import gaussian_filter1d

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

se você aumentar o sigma, poderá obter uma função mais suavizada.

Prossiga com cuidado com este. Ele modifica os valores originais e pode não ser o que você deseja.


10
Prossiga com cuidado com este. Ele modifica os valores originais e pode não ser o que você deseja.
tartaruga_casco_mole

8

Presumo que você queira dizer ajuste de curva e não anti-aliasing do contexto de sua pergunta. PyPlot não tem nenhum suporte embutido para isso, mas você pode facilmente implementar alguns ajustes básicos de curva por conta própria, como o código visto aqui , ou se você estiver usando GuiQwt, ele tem um módulo de ajuste de curva . (Você provavelmente também pode roubar o código do SciPy para fazer isso).


obrigado. Tentei dez equações diferentes e [Usando funções de base radial para suavização / interpolação] [1] rbf = Rbf(x, y), fi = rbf(xi)foi a melhor entre elas. [1]: scipy-cookbook.readthedocs.io/items/RadialBasisFunctions.html ,
Cloud Cho

1

Veja a scipy.interpolatedocumentação para alguns exemplos.

O exemplo a seguir demonstra seu uso, para interpolação linear e cúbica de spline:

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

insira a descrição da imagem aqui

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.