Skip to content

Desapegando do Excel_Dados do INMET

Bruno Dumas edited this page Dec 24, 2022 · 2 revisions

Olá pessoal!

  • A ideia deste repositório é compartilhar alguns códigos que estão me ajudando a desapegar do Excel, espero que te ajude também!

  • São mais de 15 anos de Curso Técnico, Gradução e Mestrado em Meteorologia e mais de 10 anos trabalhando com Meteorologia Operacional, então dá pra imaginar a quantidade de planilhas de Excel que já precisei elaborar e alimentar.

  • Começo hoje com a manipulação dos dados das estações automáticas de superfície do Instituto Nacional de Meteorologia (INMET).

Vossa Excelência, o dado observado!

  • Na Meteorologia, extrair informações dos dados observados é fundamental na interpretação das condições de tempo presente e na validação de modelos de previsão do tempo de curto, médio e longo prazo.

  • Além é claro da construção de um banco de dados meteorológicos que nos permita conhecer as características do clima de uma região (falarei mais de tempo e clima no próximo texto, sobre visualização e interpretação dos dados).

Dados históricos - Instituto Nacional de Meteorologia (INMET)

  • O site do INMET permite o download dos dados históricos de suas estações automáticas de 2000 até o ano presente (https://portal.inmet.gov.br/dadoshistoricos). O link das pastas zipadas com os dados de cada ano é do tipo "dadoshistoricos/'ano'.zip", assim, o primeiro passo neste código é importar os módulos os e zipfile para criar um diretório e baixar estes arquivos e extrair os arquivos zipados

    import os                     
    import zipfile                
    
    os.mkdir('dados_brutos')
    os.chdir('dados_brutos')
    
  • Para melhorar o código, usei alguns loops e f-strings:

    periodo = []
    for ano in range (2000, 2023):
      periodo.append(ano)
    
    for i in periodo:
      arquivo = [f'https://portal.inmet.gov.br/uploads/dadoshistoricos/{i}.zip']
      for i,j in zip(periodo, arquivo):
        download = os.system(f'wget -o {i}.zip {j}')
    
  • Neste caso, o comando wget -o baixa os arquivos .zip e os nomeia de acordo com a f-string de j. A seguir, os arquivos zipados são extraídos e os zips são deletados:

    for i in periodo[1:-3]:
      zipfile.ZipFile(f'/content/dados_brutos/{i}.zip').extractall('/content/dados_brutos')
      os.remove(f'/content/dados_brutos/{i}.zip')
    
  • Sim, você notou que a lista "periodo" está recortada entre os elementos 1 e -3. Manipular dados (e programar) é criar algoritmos que resolvam os problemas que aparecem pelo caminho. Neste caso, os arquivos entre 2001 e 2018 são obtidos diretamente, sem qualquer problema.

  • Para 2019 em diante, é preciso fazer uma pequena alteração no código, já que a pasta extraída do site do INMET contém uma nova pasta com o nome do ano, e aí é que realmente se encontram os dados:

    for i in periodo[-3:]:
      zipfile.ZipFile(f'/content/dados_brutos/{i}.zip').extractall(f'/content/dados_brutos/{i}')
      os.remove(f'/content/dados_brutos/{i}.zip')
    
  • Feito! Depois destes passos, a pasta dados_brutos conterá várias pastas com os dados de cada ano para as estações disponíveis.

image

  • Vamos agora para a parte divertida: concatenar e preparar o dataframe!

Concatenando e manipulando um dataframe

  • Como mencionado anteriormente, manipular uma grande quantidade de dados requer resolver problemas que aparecem pelo caminho. Neste caso, os dados estão separados em pastas para cada ano, enquanto que o ideal seria separar os dados de uma mesma estação, criando uma série temporal para cada estação analisada.

  • pandas é uma biblioteca para manipulação e análise de dados em Python importantíssima para estes casos, pois permite a importação de arquivos do tipo .csv ou .txt, entre outros, para um único dataframe.

Concatenando 20 anos de dados meteorológicos horários

  • O primeiro passo para esta análise é selecionar a estação desejada e o período avaliado. Neste exemplo, utilizarei os dados das estações Manaus-AM (A101) e Porto Alegre-RS (A801), entre 2001 e 2018. Alguns problemas encontrados pelo caminho:

    -> os dados são separados por ";";

    -> as casas decimais são indicadas por "," e os milhares por ".", justamente o contrário da formatação aceita pela bilioteca;

    -> as 8 primeiras linhas do arquivo .csv trazem informações sobre a estação automática selecionada, atrapalhando a formatação das colunas do dataframe.

  • Assim, selecionei o módulo pandas.read, que permite ler os arquivos em .csv, e utilizei as opções sep, thousands, decimal e skiprows. E, para concatenar todos esses 20 anos de dados horários em um único dataframe, utilizei o método_pandas.concat_.

    ds = None
    for i in periodo[1:19]:
      if ds is None:
        ds = pd.read_csv(f'/content/dados_brutos/{i}/INMET_N_AM_A101_MANAUS_01-01-{i}_A_31-12-{i}.CSV', sep =';', 
                                thousands = '.', decimal = ',', skiprows=[0,1,2,3,4,5,6,7], 
                                encoding='latin-1', index_col=None)
      else:
        ds = pd.concat([ds, pd.read_csv(f'/content/dados_brutos/{i}/INMET_N_AM_A101_MANAUS_01-01-{i}_A_31-12-{i}.CSV', sep =';', 
                                thousands = '.', decimal = ',', skiprows=[0,1,2,3,4,5,6,7], 
                                encoding='latin-1', index_col=None)])
    
  • Outra opção selecionada é a index_col, mas depois falamos dela.

  • Para finalizar esse tutorial, descartei algumas colunas com o método .drop e renomeei algumas colunas com o método .columns. Isso também ficará para a próxima, onde falarei mais da visualização destes dados.

    ds = ds.drop(['PRESSÃO ATMOSFERICA MAX.NA HORA ANT. (AUT) (mB)', 'PRESSÃO ATMOSFERICA MIN. NA HORA ANT. (AUT) (mB)',
              'TEMPERATURA ORVALHO MAX. NA HORA ANT. (AUT) (°C)', 'TEMPERATURA ORVALHO MIN. NA HORA ANT. (AUT) (°C)', 
              'UMIDADE REL. MAX. NA HORA ANT. (AUT) (%)', 'UMIDADE REL. MIN. NA HORA ANT. (AUT) (%)', 'Unnamed: 19'], axis=1)
    
    ds.columns = ['Data', 'HoraZ', 'Chuva', 'P', 'Rad', 'TempC', 'TempOrvC', 'TempMaxC',	'TempMinC', 'UR', 'Dir', 'Rajadas', 'Vento']
    ds['Data'] = pd.to_datetime(ds['Data'], dayfirst=True)
    ds.head()
    
  • O resultado final (por enquanto) ficou assim:

image

  • Ainda tenho muuuuuito a aprender, então quaisquer contribuições e sugestões são muito bem-vindas 🤓

Referências