Wiki

Clone wiki

topicos / Manipulação Estatística em dados Meteorologicos

# Manipulação Estatística em dados Meteorologicos

  • Manipular estruturas de dados 2d (bidimensionais) usando as estruturas Python dos pacote Numpy e PANDAS*.
  • Mineirar, manipular e aplicar tratamento estatístico em séries temporais meteorológicas.

* Pacote para análise de dados - http://pandas.pydata.org/

PARTE 01

Antes de começarmos com Séries Temporais Meteorológicas, na Parte 01 vamos utilizar uma série temporal de cotações diárias de um ativo financeiro como fonte de dados para compreender os conceitos (termos) e algumas das funcionalidades das estruturas(objetos) de manipulação de dados.

Os principais objetos do PANDAS são:

  • Series : comporta-se como um array numpy 1d.
    • Aceita quaisquer tipos de dados - Operações vetorizadas
    • Sintaxe: s = Series; Ex: s1 = [0,1,2,3,4,5]
  • DataFrame: comporta-se como uma matriz bidimensional (2d numpy array like)
    • Aceita quaisquer tipos de dados.
    • Possui um índice por padrão (1 coluna) que pode ser alterado e/ou reorganizado
    • As colunas possuem nome
    • As colunas podem ser movidas e/ou reorganizadas
    • As colunas podem ser criadas a partir de operações matemáticas (operations on rows)
    • Referências em prior rows pelo método .diff()
    • Relevantes Funções de biblioteca:
      • Média móvel rolling means in PANDAS
      • Desvio padrão, correlação, covariançia, etc
      • Gráficos (usa a biblioteca matplotlib - http://matplotlib.org/)
    • Operações vetorizadas.
    • Sintaxe: df = DataFrame(data, index=index, columns=list);
      Ex: df = DataFrame(np.random.randn(8, 3), index=index, columns=['A', 'B', 'C'])
  • Os objetos Series e Dataframe também pode se comportar como dicionários dictionary like
  • Praticamente todos os objetos possuem o método para fatiamento slicing para seleção de dados.

Obtendo (mineirando) e preparando a base de dados

Com finalidade prática, vamos usar uma série histórica, mineirando alguns dados da cotação do ativo CSNA públicos disponíveis na web via yahoo finance e armazenar um conjunto em um arquivo do tipo .csv

import pandas as pd
from pandas import DataFrame

import datetime
import pandas.io.data  ## Vamos utilizar para acesso à API do Yahoo finance e importação de dados

import matplotlib.pyplot as plt
csna3 = pd.io.data.get_data_yahoo('CSNA3.SA',
                                  start = datetime.datetime(2000,10,1),
                                  end = datetime.datetime(2015,7,10))

# o Método .head() mostra as primeiras linhas do objeto
csna3.head()

Resultado da chamada ao método ``.head()`` via comando ``csna3.head()``

# Salvar o dados do DataFrame para o formato .csv
csna3.to_csv('csna3_ohlc.csv')

A partir desse momento, não precisamos mais importar os dados do yahoo finance. Carregaremos os dados diretamente a partir do arquivo csv criado.

# Lendo o arquivo .csv [pd.read_csv('arquivo.csv')]
# Comente sobre os dois argumentos além do filename
df = pd.read_csv('csna3_ohlc.csv', index_col='Date', parse_dates=True)
df.head()
# Especificando apenas uma coluna (via string '')
df2 = df['Open']
df2.head()
Date
2000-10-02    19.50000
2000-10-03    19.66332
2000-10-04    19.49333
2000-10-05    19.23334
2000-10-06    19.36668
Name: Open, dtype: float64
# Especificando multiplas colunas (via lista[])
df3 = df[['Open', 'Close']]
df3.head()
# Removendo uma coluna
df3_tmp = df3.copy() # Criando uma cópia de segurança
del df3['Close']
df3.head()
df3 = df3_tmp.copy() # Restaurando o df3 ao estado anterior
del df3_tmp          # Removendo a cópia de segurança
df3.head()
df3.head()
# Renomeando as colunas
df3.rename(columns={'Close': 'CLOSE'}, inplace=True)
df3.head()
# Filtrando dados via condição lógica `df3[(condição-logica)]`
df4 = df3[(df3['CLOSE'] > 1)] # Seleciona onde valores de CLOSE são > 1
df4.head()
# Criando colunas com colunas a partir de operações matemáticas
df['H-L'] = df['High'] - df.Low
df.head()

Note que usamos duas formas (ambas são aceitas) para nos referir às colunas High e Low no DataFrame: df['High'] e df.Low

# Médias móveis (em pandas `pd.rolling_mean()`)
# Criando uma coluna com a Media móvel com janela de 100 períodos
df['100MA'] = pd.rolling_mean(df['Close'], 100)
print df[200:205]  # Os primeiros 100 valores serão NaN
                Open      High       Low     Close    Volume  Adj Close  Date
2001-07-11  12.66667  12.73332  12.23333  12.33334  12981600  307.66321
2001-07-12  12.27334  13.00001  12.23333  12.83666  10612800  320.21909
2001-07-13  12.83333  13.00001  12.76668  12.83333   4687200  320.13585
2001-07-16  12.83333  13.16666  12.60000  12.98333   1166400  323.87770
2001-07-17  12.87667  13.31333  12.86666  13.20000   4269600  329.28273

                H-L      100MA
Date
2001-07-11  0.49999  16.626403
2001-07-12  0.76668  16.519136
2001-07-13  0.23333  16.406469
2001-07-16  0.56666  16.295301
2001-07-17  0.44667  16.186300
# Referências em *prior rows* pelo método .diff()
# Criando uma nova colunas com valores calculados
# de uma coluna ['Close'] menos o valor anterior (por linhas)
df['Diferenca'] = df['Close'].diff()
df.head()
figure(figsize=(16,8))
# Grafico do DataFrame Inteiro
df.plot()
savefig('img-df-inteiro.png')
<matplotlib.figure.Figure at 0x7f225643bb50>
output_23_1.png

Observa-se que plotar um gráfico do DtaFrame inteiro não tem muita serventia, pois algumas informações ficam mascaradas uma vez que todas compartilham o mesmo eixo de imagem (y).

# Gráfigo de uma coluna específica
# Gráfico da média móvel 100MA
figure(figsize=(16,8))
df['100MA'].plot()
df['hpm'] = 7.02
df['hpm'].plot()
savefig('img-df-hpm-100MA.png')
output_25_0.png
# Gráfigo de colunas múltiplas
# Gráfico da média móvel 100MA e Close
figure(figsize=(16,8))
df['100MA'].plot(legend=True)
df['Close'].plot(legend=True)
#df[['Close','100MA']].plot()
savefig('img-df-Close+100MA.png')
# Gráfigo de colunas múltiplas
# Gráfico da média móvel 100MA e Close
figure(figsize=(16,8))
df[['Open','High','Low','Close','100MA']].plot()
savefig('img-df-ohlc+100MA.png')
output_27_1.png

Para traçar gráficos 3D, é necessário a importação de alguns módulos do pacote mpl_toolkits. O principal módulo aser importado é o mplot3d via comando from mpl_toolkits.mplot3d import Axes3D.

'''
    Pode-se usar um grágico 3D para mostrar o preço de fechamento
    (*Close*) do ativo em função do volume de operações e a covariância
    entre esses dados. Interessante se pudermos usar o mouse para mudar
    a visão. Nos demais casos é melhor um gráfico de espalhamento
    bidimensional.
'''
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(16,10))
graf3d = fig.gca(projection='3d')

#============================================================
#           Recriando o DataFrame com indice inteiro
#
df = pd.read_csv('csna3_ohlc.csv', parse_dates=True)
df['H-L'] = df.High - df.Low
df['100MA'] = pd.rolling_mean(df['Close'], 100)
df['Diferenca'] = df['Close'].diff()
#============================================================
# df.index é o índice dos dados
graf3d.scatter(df.index, df['H-L'], df['Close'], alpha=0.5)
# Nomeando os 3 eixos
graf3d.set_xlabel('Index')
graf3d.set_ylabel('H-L')
graf3d.set_zlabel('Close')
fig.show()
savefig('img-df-3d-HLxClose.png')

# Comportamento de H-L responde a variação no Volume
fig = plt.figure(figsize=(16,10))
graf3d =fig.gca(projection='3d')
graf3d.scatter(df.index, df['H-L'], df['Volume'], alpha=0.5)
# Nomeando os 3 eixos
graf3d.set_xlabel('Index')
graf3d.set_ylabel('H-L')
graf3d.set_zlabel('Volume')
fig.show()
savefig('img-df-3d-HLxVol.png')
output_29_0.png output_29_1.png
""" Adicionando uma coluna ao DataFrame para adicionar o cálculo do
    valor do Desvio Padrão (*STD*)

    .sublot(rows,cols, plot-number)
"""
#============================================================
#         Recriando o DataFrame com indice sendo a Data
#
df = pd.read_csv('csna3_ohlc.csv', index_col='Date', parse_dates=True)
df['H-L'] = df.High - df.Low
df['100MA'] = pd.rolling_mean(df['Close'], 100, min_periods=1)
df['Diferenca'] = df['Close'].diff()
#============================================================

df['STD'] = pd.rolling_std(df['Close'], 25, min_periods=1)

fig = plt.figure(figsize=(16,10))

# Criando eixos para multiplot
# Superior (Linha 1)
ax1 = plt.subplot(2,1,1)
# ax1.plot(df['Close'])             # usando matplotlib diretamente
df['Close'].plot(legend=True)       # usando pandas

# Inferior (Linha 2)
# se quiser compartilhar o eixo .subplot(2,1,2, sharex = ax1)
ax2 = plt.subplot(2,1,2)
df['STD'].plot(legend=True)
fig.show()
savefig('img-df-mpl-close-std.png')
output_31_0.png

A Descrição Estatística de um DataFrame (Das séries em geral) é obtida pelo método comum .describe.

O exemplo abaixo permite estimar os mais comuns (principais - Distribuição Normal e Escalas) parâmetros estatísticos sobre uma série de dados.

Uma coluna de um DataFrame possui o método .describe()

# Já que cada coluna do DataFrame comporta-se como uma série,
# pode-se invocar o método `.describe` em todo o DataFrame

df.describe()
'''
    Correlação = Relação na variação entre duas grandezas. Quão
    influente é a variação de uma variável como causa da variação
    da outra. Obs: Correlação não é causa.

    Covariância = Medida da força da correlação. Quão forte é a
    influência de uma sobre a outra.
'''

# Mostrando a correlação
df.corr()
# Mostrando a Covariância
df.cov()
# Se quisermos apenas a estatística comparativa entre duas variáveis
df[['Volume', 'H-L']].corr()

**Exercício 1 - ** Construa uma tabela das correlações entre vários ativos. Use os dados públicos Yahoo finance para obter as séries históricas e descreva como você observa as correlações entre os ativos de alguns segmentos.

**Exercício 2 - ** Aplique os conceitos (termos) e as funcionalidades das estruturas(objetos) que você aprendeu nessa aula em um conjunto de séries históricas meteorológicas.

Fonte de dados para utilizar: http://200.132.24.235/csda/topicos-met.csv.zip


Map Functions

Vamos refazer algumas operações utilizando map functions ao invés dos métodos do pandas. É importante saber como fazer algumas coisas do jeito "difícil" ou como se diz "à unha", pois nem sempre se quer utilizar black boxes embora tudo no python seja open source.

O Exemplo abaixo ilustra a possibilidade de você criar sua própria função e aplicá-la a cada valor (linha por linha) da coluna de um DataFrame. Esse exemplo é interessante pois a sua função particular pode receber quantos e quais parâmetros você quiser.

#============================================================
#         Criando o DataFrame com indice sendo a Data
#
df = pd.read_csv('csna3_ohlc.csv', index_col='Date', parse_dates=True)
#============================================================
import random

def function(data):
    '''
        Recebe o parâmetro data como argumento e o retorna multiplicado
        por um numero aleatorio entre 0 e 5
    '''
    x = random.randrange(0,5)
    return data*x



df['Multiple'] = map(function, df['Close'])
df.head()

Elaborado por Hans Rogerio Zimermann para o curso FSC878 - Topicos Especiais II PPGMET - UFSM.

Updated