気候データはいくつかの分野で重要な役割を果たしており、農業、都市計画、天然資源管理などの分野に影響を与える研究や予測に役立ちます。
国立気象研究所 (INMET) は、ウェブサイトで気象データベース (BDMEP) を毎月提供しています。このデータベースには、ブラジル全土に分布する何百もの測定局によって収集された一連の過去の気候情報が含まれています。 BDMEP では、降雨量、気温、湿度、風速に関する詳細なデータが見つかります。
このデータは 1 時間ごとに更新されるため、非常に大量であり、詳細な分析と情報に基づいた意思決定のための豊富な基礎を提供します。
この投稿では、INMET-BDMEP から気候データを収集して処理する方法を説明します。 INMET Web サイトで入手可能な生データ ファイルを収集し、分析を容易にするためにこのデータを処理します。
1. 必要な Python パッケージ
前述の目的を達成するには、次の 3 つのパッケージをインストールするだけで済みます。
- httpx HTTP リクエストを作成します
- データの読み取りと処理のための Panda
- tqdm は、プログラムがファイルをダウンロードまたは読み取るときにターミナルに分かりやすい進行状況バーを表示します
必要なパッケージをインストールするには、ターミナルで次のコマンドを実行します。
pip install httpx pandas tqdm
たとえば、詩で仮想環境 (venv) を使用している場合は、次のコマンドを使用します。
poetry add httpx pandas tqdm
2. ファイルの収集
2.1 ファイルの URL パターン
BDMEP データ ファイルのアドレスは、非常に単純なパターンに従います。パターンは次のとおりです。
https://portal.inmet.gov.br/uploads/dadoshistoricos/{year}.zip
変更される部分はファイル名だけであり、これは単にデータの参照年です。毎月、最新 (現在) 年のファイルが更新されたデータに置き換えられます。
これにより、利用可能なすべての年からデータ ファイルを自動的に収集するコードを簡単に作成できます。
実際、利用可能な歴史シリーズは 2000 年に始まります。
2.2 収集戦略
INMET-BDMEP からデータ ファイルを収集するには、httpx ライブラリを使用して HTTP リクエストを作成し、tqdm ライブラリを使用してターミナルにわかりやすい進行状況バーを表示します。
まず、必要なパッケージをインポートしましょう:
import datetime as dt from pathlib import Path import httpx from tqdm import tqdm
INMET-BDMEP データ ファイルの URL パターンはすでに特定されています。次に、年を引数として受け取り、その年のファイルの URL を返す関数を作成しましょう。
def build_url(year): return f"https://portal.inmet.gov.br/uploads/dadoshistoricos/{year}.zip"
URL ファイルが更新されたかどうかを確認するには、HTTP リクエストによって返されたヘッダーに存在する情報を使用できます。適切に構成されたサーバーでは、HEAD メソッドを使用してこのヘッダーのみをリクエストできます。この場合、サーバーは適切に構成されているため、この方法を使用できます。
HEAD リクエストに対する応答は次の形式になります:
Mon, 01 Sep 2024 00:01:00 GMT
この日付/時刻を解析するために、Python で次の関数を作成しました。この関数は 文字列 を受け取り、日時オブジェクトを返します。
def parse_last_modified(last_modified: str) -> dt.datetime: return dt.datetime.strptime( last_modified, "%a, %d %b %Y %H:%M:%S %Z" )
したがって、文字列補間 (f-strings) を使用して、最終変更の日付/時刻をダウンロードするファイルの名前に含めることができます。
def build_local_filename(year: int, last_modified: dt.datetime) -> str: return f"inmet-bdmep_{year}_{last_modified:%Y%m%d}.zip"
この方法により、最新のデータを含むファイルがローカル ファイル システムに既に存在するかどうかを簡単に確認できます。ファイルがすでに存在する場合は、プログラムを終了できます。それ以外の場合は、ファイルの収集を続行し、サーバーにリクエストを行う必要があります。
以下の download_year 関数は、特定の年のファイルをダウンロードします。ファイルが宛先ディレクトリにすでに存在する場合、関数は何もせずに単に戻ります。
ファイルのダウンロード中に tqdm を使用してターミナルにわかりやすい進行状況バーを表示する方法に注目してください。
def download_year( year: int, destdirpath: Path, blocksize: int = 2048, ) -> None: if not destdirpath.exists(): destdirpath.mkdir(parents=True) url = build_url(year) headers = httpx.head(url).headers last_modified = parse_last_modified(headers["Last-Modified"]) file_size = int(headers.get("Content-Length", 0)) destfilename = build_local_filename(year, last_modified) destfilepath = destdirpath / destfilename if destfilepath.exists(): return with httpx.stream("GET", url) as r: pb = tqdm( desc=f"{year}", dynamic_ncols=True, leave=True, total=file_size, unit="iB", unit_scale=True, ) with open(destfilepath, "wb") as f: for data in r.iter_bytes(blocksize): f.write(data) pb.update(len(data)) pb.close()
2.3 ファイルの収集
必要な関数がすべて揃ったので、INMET-BDMEP データ ファイルを収集できます。
for ループを使用すると、利用可能なすべての年のファイルをダウンロードできます。次のコードはまさにそれを行います。 2000 年から今年まで。
destdirpath = Path("data") for year in range(2000, dt.datetime.now().year + 1): download_year(year, destdirpath)
3. データの読み取りと処理
INMET-BDMEP 生データ ファイルをダウンロードすると、データを読み取り、処理できるようになります。
必要なパッケージをインポートしましょう:
import csv import datetime as dt import io import re import zipfile from pathlib import Path import numpy as np import pandas as pd from tqdm import tqdm
3.1 ファイル構造
INMET が提供する ZIP ファイル内には、気象観測所ごとに 1 つずつ、複数の CSV ファイルがあります。
Porém, nas primeiras linhas desses arquivos CSV encontramos informações sobre a estação, como a região, a unidade federativa, o nome da estação, o código WMO, as coordenadas geográficas (latitude e longitude), a altitude e a data de fundação. Vamos extrair essas informações para usar como metadados.
3.2 Leitura dos dados com pandas
A leitura dos arquivos será feita em duas partes: primeiro, será feita a leitura dos metadados das estações meteorológicas; depois, será feita a leitura dos dados históricos propriamente ditos.
3.2.1 Metadados
Para extrair os metadados nas primeiras 8 linhas do arquivo CSV vamos usar o pacote embutido csv do Python.
Para entender a função a seguir é necessário ter um conhecimento um pouco mais avançado de como funciona handlers de arquivos (open), iteradores (next) e expressões regulares (re.match).
def read_metadata(filepath: Path | zipfile.ZipExtFile) -> dict[str, str]: if isinstance(filepath, zipfile.ZipExtFile): f = io.TextIOWrapper(filepath, encoding="latin-1") else: f = open(filepath, "r", encoding="latin-1") reader = csv.reader(f, delimiter=";") _, regiao = next(reader) _, uf = next(reader) _, estacao = next(reader) _, codigo_wmo = next(reader) _, latitude = next(reader) try: latitude = float(latitude.replace(",", ".")) except: latitude = np.nan _, longitude = next(reader) try: longitude = float(longitude.replace(",", ".")) except: longitude = np.nan _, altitude = next(reader) try: altitude = float(altitude.replace(",", ".")) except: altitude = np.nan _, data_fundacao = next(reader) if re.match("[0-9]{4}-[0-9]{2}-[0-9]{2}", data_fundacao): data_fundacao = dt.datetime.strptime( data_fundacao, "%Y-%m-%d", ) elif re.match("[0-9]{2}/[0-9]{2}/[0-9]{2}", data_fundacao): data_fundacao = dt.datetime.strptime( data_fundacao, "%d/%m/%y", ) f.close() return { "regiao": regiao, "uf": uf, "estacao": estacao, "codigo_wmo": codigo_wmo, "latitude": latitude, "longitude": longitude, "altitude": altitude, "data_fundacao": data_fundacao, }
Em resumo, a função read_metadata definida acima lê as primeiras oito linhas do arquivo, processa os dados e retorna um dicionário com as informações extraídas.
3.2.2 Dados históricos
Aqui, finalmente, veremos como fazer a leitura do arquivo CSV. Na verdade é bastante simples. Basta usar a função read_csv do Pandas com os argumentos certos.
A seguir está exposto a chamada da função com os argumentos que eu determinei para a correta leitura do arquivo.
pd.read_csv( "arquivo.csv", sep=";", decimal=",", na_values="-9999", encoding="latin-1", skiprows=8, usecols=range(19), )
Primeiro é preciso dizer que o caractere separador das colunas é o ponto-e-vírgula (;), o separador de número decimal é a vírgula (,) e o encoding é latin-1, muito comum no Brasil.
Também é preciso dizer para pular as 8 primeiras linhas do arquivo (skiprows=8), que contém os metadados da estação), e usar apenas as 19 primeiras colunas (usecols=range(19)).
Por fim, vamos considerar o valor -9999 como sendo nulo (na_values="-9999").
3.3 Tratamento dos dados
Os nomes das colunas dos arquivos CSV do INMET-BDMEP são bem descritivos, mas um pouco longos. E os nomes não são consistentes entre os arquivos e ao longo do tempo. Vamos renomear as colunas para padronizar os nomes e facilitar a manipulação dos dados.
A seguinte função será usada para renomear as colunas usando expressões regulares (RegEx):
def columns_renamer(name: str) -> str: name = name.lower() if re.match(r"data", name): return "data" if re.match(r"hora", name): return "hora" if re.match(r"precipita[çc][ãa]o", name): return "precipitacao" if re.match(r"press[ãa]o atmosf[ée]rica ao n[íi]vel", name): return "pressao_atmosferica" if re.match(r"press[ãa]o atmosf[ée]rica m[áa]x", name): return "pressao_atmosferica_maxima" if re.match(r"press[ãa]o atmosf[ée]rica m[íi]n", name): return "pressao_atmosferica_minima" if re.match(r"radia[çc][ãa]o", name): return "radiacao" if re.match(r"temperatura do ar", name): return "temperatura_ar" if re.match(r"temperatura do ponto de orvalho", name): return "temperatura_orvalho" if re.match(r"temperatura m[áa]x", name): return "temperatura_maxima" if re.match(r"temperatura m[íi]n", name): return "temperatura_minima" if re.match(r"temperatura orvalho m[áa]x", name): return "temperatura_orvalho_maxima" if re.match(r"temperatura orvalho m[íi]n", name): return "temperatura_orvalho_minima" if re.match(r"umidade rel\. m[áa]x", name): return "umidade_relativa_maxima" if re.match(r"umidade rel\. m[íi]n", name): return "umidade_relativa_minima" if re.match(r"umidade relativa do ar", name): return "umidade_relativa" if re.match(r"vento, dire[çc][ãa]o", name): return "vento_direcao" if re.match(r"vento, rajada", name): return "vento_rajada" if re.match(r"vento, velocidade", name): return "vento_velocidade"
Agora que temos os nomes das colunas padronizados, vamos tratar a data/hora. Os arquivos CSV do INMET-BDMEP têm duas colunas separadas para data e hora. Isso é inconveniente, pois é mais prático ter uma única coluna de data/hora. Além disso existem inconsistências nos horários, que às vezes têm minutos e às vezes não.
As três funções a seguir serão usadas para criar uma única coluna de data/hora:
def convert_dates(dates: pd.Series) -> pd.DataFrame: dates = dates.str.replace("/", "-") return dates def convert_hours(hours: pd.Series) -> pd.DataFrame: def fix_hour_string(hour: str) -> str: if re.match(r"^\d{2}\:\d{2}$", hour): return hour else: return hour[:2] + ":00" hours = hours.apply(fix_hour_string) return hours def fix_data_hora(d: pd.DataFrame) -> pd.DataFrame: d = d.assign( data_hora=pd.to_datetime( convert_dates(d["data"]) + " " + convert_hours(d["hora"]), format="%Y-%m-%d %H:%M", ), ) d = d.drop(columns=["data", "hora"]) return d
Existe um problema com os dados do INMET-BDMEP que é a presença de linhas vazias. Vamos remover essas linhas vazias para evitar problemas futuros. O código a seguir faz isso:
# Remove empty rows empty_columns = [ "precipitacao", "pressao_atmosferica", "pressao_atmosferica_maxima", "pressao_atmosferica_minima", "radiacao", "temperatura_ar", "temperatura_orvalho", "temperatura_maxima", "temperatura_minima", "temperatura_orvalho_maxima", "temperatura_orvalho_minima", "umidade_relativa_maxima", "umidade_relativa_minima", "umidade_relativa", "vento_direcao", "vento_rajada", "vento_velocidade", ] empty_rows = data[empty_columns].isnull().all(axis=1) data = data.loc[~empty_rows]
Problema resolvido! (•̀ᴗ•́)و ̑̑
3.4 Encapsulando em funções
Para finalizar esta seção vamos encapsular o código de leitura e tratamento em funções.
Primeiro uma função para a leitura do arquivo CSV contino no arquivo comprimido.
def read_data(filepath: Path) -> pd.DataFrame: d = pd.read_csv( filepath, sep=";", decimal=",", na_values="-9999", encoding="latin-1", skiprows=8, usecols=range(19), ) d = d.rename(columns=columns_renamer) # Remove empty rows empty_columns = [ "precipitacao", "pressao_atmosferica", "pressao_atmosferica_maxima", "pressao_atmosferica_minima", "radiacao", "temperatura_ar", "temperatura_orvalho", "temperatura_maxima", "temperatura_minima", "temperatura_orvalho_maxima", "temperatura_orvalho_minima", "umidade_relativa_maxima", "umidade_relativa_minima", "umidade_relativa", "vento_direcao", "vento_rajada", "vento_velocidade", ] empty_rows = d[empty_columns].isnull().all(axis=1) d = d.loc[~empty_rows] d = fix_data_hora(d) return d
Tem um problema com a função acima. Ela não lida com arquivos ZIP.
Criamos, então, a função read_zipfile para a leitura de todos os arquivos contidos no arquivo ZIP. Essa função itera sobre todos os arquivos CSV no arquivo zipado, faz a leitura usando a função read_data e os metadados usando a função read_metadata, e depois junta os dados e os metadados em um único DataFrame.
def read_zipfile(filepath: Path) -> pd.DataFrame: data = pd.DataFrame() with zipfile.ZipFile(filepath) as z: files = [zf for zf in z.infolist() if not zf.is_dir()] for zf in tqdm(files): d = read_data(z.open(zf.filename)) meta = read_metadata(z.open(zf.filename)) d = d.assign(**meta) data = pd.concat((data, d), ignore_index=True) return data
No final, basta usar essa última função definida (read_zipfile) para fazer a leitura dos arquivos ZIP baixados do site do INMET. (. ❛ ᴗ ❛.)
df = reader.read_zipfile("inmet-bdmep_2023_20240102.zip") # 100%|████████████████████████████████████████████████████████████████████████████████| 567/567 [01:46 <h2> 4. Gráfico de exemplo </h2> <p>Para finalizar, nada mais satisfatório do que fazer gráficos com os dados que coletamos e tratamos. ヾ(≧▽≦*)o</p> <p>Nessa parte uso o R com o pacote tidyverse para fazer um gráfico combinando a temperatura horária e a média diária em São Paulo.<br> </p> <pre class="brush:php;toolbar:false">library(tidyverse) dados filter(uf == "SP") # Temperatura horária em São Paulo dados_sp_h group_by(data_hora) |> summarise( temperatura_ar = mean(temperatura_ar, na.rm = TRUE), ) # Temperatura média diária em São Paulo dados_sp_d group_by(data = floor_date(data_hora, "day")) |> summarise( temperatura_ar = mean(temperatura_ar, na.rm = TRUE), ) # Gráfico combinando temperatura horária e média diária em São Paulo dados_sp_h |> ggplot(aes(x = data_hora, y = temperatura_ar)) + geom_line( alpha = 0.5, aes( color = "Temperatura horária" ) ) + geom_line( data = dados_sp_d, aes( x = data, y = temperatura_ar, color = "Temperatura média diária" ), linewidth = 1 ) + labs( x = "Data", y = "Temperatura (°C)", title = "Temperatura horária e média diária em São Paulo", color = "Variável" ) + theme_minimal() + theme(legend.position = "top") ggsave("temperatura_sp.png", width = 16, height = 8, dpi = 300)
5. Conclusão
Neste texto mostrei como coletar e tratar os dados climáticos do INMET-BDMEP. Os dados coletados são muito úteis para estudos e previsões nas mais variadas áreas. Com os dados tratados, é possível fazer análises e gráficos como o que mostrei no final.
Espero que tenha gostado do texto e que tenha sido útil para você.
このテキストで示した関数を含む Python パッケージを作成しました。パッケージは私の Git リポジトリから入手できます。必要に応じて、パッケージをダウンロードして、独自のコードで関数を使用できます。
Git リポジトリ: https://github.com/dankkom/inmet-bdmep-data
(~ ̄▽ ̄)~
以上がINMET-BDMEP 気候データの収集と処理の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

toAppendElementStoapyThonList、usetheappend()methodforsingleelements、extend()formultipleElements、andinsert()forspecificopsitions.1)useappend()foraddingoneElementatheend.2)useextend()toaddmultipleelementseffictience.3)

To CreateapythonList、usesquareBrackets []およびSeparateItemswithcommas.1)listsaredynamicandcanholdmixdatatypes.2)useappend()、remaid()、andslicingformanipulation.3)listcompreheNsionsionsionsionsionsionsionsionsionsionsionsionsionsionsionsionsionsientionforcreating.4)

金融、科学研究、医療、およびAIの分野では、数値データを効率的に保存および処理することが重要です。 1)財務では、メモリマッピングされたファイルとnumpyライブラリを使用すると、データ処理速度が大幅に向上する可能性があります。 2)科学研究の分野では、HDF5ファイルはデータストレージと取得用に最適化されています。 3)医療では、インデックス作成やパーティション化などのデータベース最適化テクノロジーがデータのパフォーマンスを向上させます。 4)AIでは、データシャーディングと分散トレーニングがモデルトレーニングを加速します。システムのパフォーマンスとスケーラビリティは、適切なツールとテクノロジーを選択し、ストレージと処理速度の間のトレードオフを検討することにより、大幅に改善できます。

pythonarraysarasarecreatedusingthearraymodule、notbuilt-inlikelists.1)importthearraymodule.2)specifytheTypecode、emg。、 'i'forintegers.3)Arraysofferbettermemoreefficiency forhomogeneousdatabutlasefutablethanlists。

Shebangラインに加えて、Pythonインタープリターを指定するには多くの方法があります。1。コマンドラインから直接Pythonコマンドを使用します。 2。バッチファイルまたはシェルスクリプトを使用します。 3. makeやcmakeなどのビルドツールを使用します。 4. Invokeなどのタスクランナーを使用します。各方法には利点と短所があり、プロジェクトのニーズに合った方法を選択することが重要です。

forhandlinglaredataSetsinpython、usenumpyArrays forbetterperformance.1)numpyarraysarememory-effictientandfasterfornumericaloperations.2)nusinnnnedarytypeconversions.3)レバレッジベクトル化は、測定済みのマネージメーシェイメージーウェイズデイタイです

inpython、listsusedynamicmemoryallocation with allocation、whilenumpyArraysalocatefixedmemory.1)listsallocatemorememorythanneededededinitivative.2)numpyArrayasallocateexactmemoryforements、rededicablebutlessflexibilityを提供します。

inpython、youcanspecthedatatypeyfelemeremodelernspant.1)usenpynernrump.1)usenpynerp.dloatp.ploatm64、フォーマーpreciscontrolatatypes。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

WebStorm Mac版
便利なJavaScript開発ツール

SublimeText3 中国語版
中国語版、とても使いやすい

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

MantisBT
Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。
