Interpolando funções em seus dados usando Python [PARTE 1]

Faaaala cientista! Tudo tranquilo?
Você tem aquele conjuntinho de dados maroto e quer estimar o comportamento dele em alguns pontos que não estão lá? Esse post é pra você!
Hoje veremos como estimar novos pontos em um conjunto por meio de pontos já existentes. Esse processo se chama interpolação. Vamos ver como faz?

Para mostrar a interpolação de uma função entre os pontos continuaremos usando o arquivo csv que mostra a flutuação das ações da Petrobrás, como vimos nesse post aqui. Fique tranquilo: instruções para obtê-lo estão no começo do código dessa semana.

Dividimos todo o código em três partes, OK? Vamos a elas:

from scipy.interpolate import interp1d
from urllib.request import urlopen

import matplotlib.pyplot as plt
import numpy as np

url = 'http://real-chart.finance.yahoo.com/table.csv?s=PETR4.SA&d=9&e=17&f=2015&g=d&a=0&b=3&c=2000&ignore=.csv'
petr_csv = urlopen(url)
data_petr = np.genfromtxt(petr_csv, delimiter=',', dtype=None)

# Dando uma olhada no cabeçalho dos dados.
data_petr[0:4, 0:]

Na primeira parte indicamos as funções e pacotes que serão utilizados. Também entramos com a URL que contém o arquivo que iremos estudar. Usamos a função urlopen() para acessá-lo, e atribuímos seu conteúdo à variável data_petr por meio da função genfromtxt(). Veja que o argumento de urlopen é a URL que desejamos acessar, enquanto que passamos vários parâmetros a genfromtxt():

  • delimiter = ‘,’ indica que o delimitador entre os campos é a vírgula.
  • dtype=None instrui genfromtxt() a não atribuir tipo de dados à variável. Faremos isso depois.

Depois disso damos uma olhada nas cinco primeiras linhas do arquivo, usando data_petr[0:4, :]. O resultado é esse aqui:

array([[b'Date', b'Open', b'High', b'Low', b'Close', b'Volume', b'Adj Close'],
       [b'2015-10-16', b'7.99', b'8.08', b'7.81', b'7.95', b'42963800', b'7.95'],
       [b'2015-10-15', b'8.00', b'8.07', b'7.67', b'8.00', b'61444100', b'8.00'],
       [b'2015-10-14', b'8.07', b'8.23', b'7.89', b'7.96', b'75339100', b'7.96']], 
      dtype='|S11')

Veja que a primeira linha contém os nomes das variáveis, enquanto que a primeira coluna contém as datas. Vamos trabalhar com a coluna ‘Adj Close’.

adj_close = np.array(data_petr[1:, 6:].flatten(), dtype=float)
plt.figure()
plt.plot(adj_close, 'r')
plt.xlabel('Dias')
plt.ylabel('Preço de fechamento ajustado')
plt.show()

Nessa parte do código atribuímos a coluna ‘Adj Close’, sem a primeira linha, (data_petr[1:, 6:]) à variável adj_close. Lembre-se que Python começa os índices em zero! A primeira linha é 0; a sétima coluna é 6. Usamos o argumento flatten() para garantir que teremos um vetor de uma dimensão, e dizemos que os dados são pontos flutuantes (dtype=float).

Depois de arrumar os dados fazemos um gráfico, com rótulos em X e Y. O gráfico resultante é esse aqui:

plot_adjclose

Fizemos esse gráfico com a ajuda do Pandas nesse post aqui. Corre lá e dá uma olhada!

# Utilizamos o tamanho do vetor pra criar o eixo X.
fim = np.shape(adj_close)[0]
adj_x = np.linspace(0, fim, fim, endpoint=True)

# Interpolando pontos em toda a função.
interpolacao_linear = interp1d(adj_x, adj_close, kind='linear')
interpolacao_adjclose = interpolacao_linear(adj_x)

# Verificando a interpolação.
plt.figure()
plt.plot(adj_x, adj_close, 'ro', adj_x, interpolacao_adjclose, 'k--')
plt.xlabel('Dias')
plt.ylabel('Preço de fechamento ajustado')
plt.show()

Agora é hora de interpolar os dados! Usamos a função interp1d, presente em scipy.interpolate. Ela gera uma função de pontos baseados nos nossos dados. Seu argumento ‘kind’ especifica o tipo de interpolação utilizada. Os argumentos válidos são ‘linear’, ‘nearest’, ‘zero’, ‘slinear’, ‘quadratic’, ‘cubic’. O padrão é ‘linear’.
Os argumentos ‘slinear’, ‘quadratic’ e ‘cubic’ se referem à interpolação com uma spline de primeira, segunda ou terceira ordem. Caso seja utilizado um inteiro, ele expressará a ordem da spline que será utilizada.
Para ter mais informações, veja a documentação de interp1d no SciPy.

A figura a seguir mostra o gráfico original (em bolinhas vermelhas) e a interpolação (traços pretos):

adjclose_interp

Parece que ficou bom! Vamos ver o efeito em um intervalo menor:

# Vamos testar em um intervalo menor.
# Tomaremos os primeiros dez dias.
adj_pedaco = adj_close[:10]

# Criaremos um eixo X de 0 a 10, com 50 pontos:
eixo_x = np.linspace(0, 10)

# Usamos a função interpolacao_linear com os valores
# do eixo X.
interp_pedaco_lin = interpolacao_linear(eixo_x)
# Verificando a interpolação.
plt.figure()
plt.plot(eixo_x, interp_pedaco_lin, 'k+', adj_pedaco, 'ro')
plt.xlabel('Dias')
plt.ylabel('Preço de fechamento ajustado - Interpolação linear')
plt.show()

# Testando agora a interpolação cúbica (kind='cubic').
interpolacao_cubica = interp1d(adj_x, adj_close, kind='cubic')
interp_pedaco_cub = interpolacao_cubica(eixo_x)
# Verificando a interpolação.
plt.figure()
plt.plot(eixo_x, interp_pedaco_cub, 'k+', adj_pedaco, 'ro')
plt.xlabel('Dias')
plt.ylabel('Preço de fechamento ajustado - Interpolação cúbica')
plt.show()

Tomamos dez dias do intervalo original, criamos um vetor eixo_X com 50 elementos entre 0 e 10 e interpolamos valores para os pontos de eixo_x. Depois só plotamos os resultados. Usamos tanto a interpolação linear quanto a cúbica (kind=’cubic’). O resultado da interpolação linear é esse aqui:

interp_linear

Por sua vez, o resultado da interpolação cúbica é esse:

interp_cubica

Viu que bacana? Conseguimos interpolar funções em nossos dados com apenas uma função do SciPy!

Vimos dezenas de informações nesse post! Trabalhamos de novo com a função urlopen, abrimos um arquivo .csv com numpy, separamos dados do nosso arquivo, usamos dois tipos de interpolação (linear e cúbica) e fizemos vários gráficos. Ufa! Tente utilizar outras partes do gráfico na interpolação! Use também outros argumentos para interpolar; por exemplo, kind=’slinear’ ou kind=5. Altere também os argumentos do gráfico! Deixe-o com a sua cara! Semana que vem continuamos a falar sobre interpolação, OK?
Valeu cientista! Um giga abraço!


Gostou? Curta e compartilhe com seus amigos!
Quer baixar os códigos do Programando Ciência? Corre lá no nosso GitHub!
Faça uma doação pro Programando Ciência!
Curta a gente também no Facebook: www.facebook.com/programandociencia
Estou no Twitter! Siga-me se puder! @alexdesiqueira

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s