Pythonで拡張アメダス新フォーマット(WEA2)を読む(3)
2024年11月6日
前回からの続きです。前回は気温のデータを読み込みました。今回は、WEA2からすべてのデータをまとめて読みます。
地点データをまとめて読み込む
WEA2の構造は前回のとおりです。この例では指定された地点(東京、363)のデータをまとめて読み込んでCSVの形式で保存します。
CSVの形式は値の種類ごとに時系列の「列」として出力します。地点番号や日平均のデータは取り除きます。
処理内容は以下の通りです。
- numpyで1地点分のデータをまとめて読み込む
- 10レコードに整形
- Pandas/DataFrameに変換
- 最初の3列(地点番号、値の種類、年)は使わないので削除
- 最後の平均値366日分も同様に削除
- 各値のリマークを削除
- 列と行を入れ替える(WEA2は「行」ごとに値がまとまているので、時系列の「列」に変換する)
- 値の単位を換算
- 各列にラベルを付けてCSVへ保存する
Pythonコード
実際の処理は以下のようになります。この例では東京(363)を読み込んで出力しています。
# coding: utf-8
# Example code to read the extended AMeDAS WEA2 file.
# author Yuichi Yasuda @ quattro corporate design
# copyright 2024 quattro corporate design. All right reserved.
import numpy as np
import pandas as pd
import math
import os
# WEA2 File path
WEA2_FILE = r"E:\EAD\PRY1120.wea2"
BLOCK_NO = 363 # Station number, Tokyo(3630)
# BLOCK_NO = 444 # Station number, Irozaki(4440)
# Constants
RECORD_LENGTH = 18306 # Length of one record in bytes
NUM_RECORDS = 11 # Number of records
BLOCK_LENGTH = RECORD_LENGTH * NUM_RECORDS # Data size for one location in bytes
TOTAL_LENGTH = RECORD_LENGTH * 10 # Actual data size excluding the first location record in bytes
NVALS = int(TOTAL_LENGTH / 2) # Number of int16 values
# Check if file exists
if not os.path.exists(WEA2_FILE):
raise FileNotFoundError(f"The file {WEA2_FILE} does not exist.")
try:
# Read binary file
with open(WEA2_FILE, "rb") as f:
# Move to the start position of the target location
f.seek(BLOCK_LENGTH * (BLOCK_NO-1))
# Skip the first record ([0]location information)
f.seek(RECORD_LENGTH, 1)
# Read data for [1]temperature to [10]relative humidity
data = np.fromfile(f, dtype=np.int16, count=NVALS)
except Exception as e:
raise IOError(f"An error occurred while reading the file: {e}")
# Reshape data to DataFrame(10 records x 9153 x int16)
data = data.reshape((10, 3 + 366 * 24 + 366))
df = pd.DataFrame(data)
# Remove the first 3 columns (location number, type, year)
df = df.iloc[:, 3:]
# Extract the first 365*24 columns, excluding the 366-day daily averages
df = df.iloc[:, :365 * 24]
# Reset the column numbers of the dataframe from 0 to 8759
df.columns = range(8760)
# Remove the remark (Remove the first digit of the value)
# Divide all values in df by 10 using math.floor()
df = df.applymap(lambda x: math.floor(x / 10))
# Transpose the rows and columns of df
df = df.T
# Correspondence between values and units
# Temperature, Absolute Humidity, Global Solar Radiation, Atmospheric Radiation, Wind Direction, Wind Speed, Precipitation, Sunshine Duration, Local Pressure, Relative Humidity
# 0.1degC, 0.1g/kg, 0.01MJ, 0.01MJ, 16 directions, 0.1m/s, 0.1mm, 0.01h, hPa, 0.1%
# Unit conversion factors and conversion of df units
unitf = [0.1, 0.1, 0.01, 0.01, 1.0, 0.1, 1.0, 0.01, 1.0, 0.1]
df = df * unitf
labels = ["Temperature[C]", "Absolute Humidity[g/kg]", "Global Solar Radiation[MJ]", "Atmospheric Radiation[MJ]", "Wind Direction[-]", "Wind Speed[m/s]", "Precipitation[mm]", "Sunshine Duration[h]", "Local Pressure[hPa]", "Relative Humidity[%]"]
df.columns = labels
# Write df to a CSV file
df.to_csv(f"EA_{BLOCK_NO}.csv", index=False, header=True)
出力例
図はCSVをExcelで開いた例です。各列ごとに値が時系列で出力されます。サクッと確認した感じ正しい値が出力されていると思います。試される方はDataNavi8の出力と比べてからご利用ください。
なにか、不具合などあればコメントください。
動作環境
以下の環境で動作を確認しています。
- Windows11 Pro(64bit, 24H2)
- Python 3.12.4
- 標準年EA気象データ2020年版(WEA2)