matplotlib:気象データ処理のTIPS
作成者:山下陽介(国立環境研究所)
目次
[top]CSVファイル
CSVファイルの形式
CSV(Comma-Separated Values)は、カンマ区切りのテキストデータ
時刻,項目1,項目2,項目3 時刻1,データ1-1,データ1-2,データ1-3 時刻2,データ2-1,データ2-2,データ2-3 ...*ヘッダがない場合を扱うことも可能
CSVファイルの読み込み
pandasのread_csvを用いる方法
import pandas as pd df = pd.read_csv("ファイル名")*読み込み時にUnicodeDecodeErrorが出る場合は、CSVファイル読み込み時のエラー参照
CSVファイルの時刻処理
- 例:1列目が時刻データの場合
import pandas as pd df = pd.read_csv("ファイル名", parse_dates=[0], index_col=[0])
parse_datesには時刻データとして処理する列、index_colにはindexとして扱う列を指定
時刻データはdf.indexになる - 例:1列目が年、2列目が月のように複数列に時刻データが入っている場合
df = pd.read_csv("ファイル名", parse_dates=[[0, 1]], index_col=[0])
時刻データはdf.indexになり、年、月単独のデータは参照できない - 例:1列目が月、2列目が年のように並びが逆の場合
df = pd.read_csv("ファイル名", parse_dates=[[1, 0]], index_col=[0])
- 例:読み込んだ年、月の時刻データも残したい場合
df = pd.read_csv("ファイル名", parse_dates=[[0, 1]], index_col=[0], keep_date_col=True)
時刻データはdf.index、年、月のデータはdf.year、df.monthなどになる(yearやmonthなどは、ヘッダに記述された名前になる)
CSVファイルの行処理
- 例:1行目にヘッダがなく、1行目からデータが入っている場合
import pandas as pd df = pd.read_csv("ファイル名", header=None)
- 例:ヘッダがない場合に、読み込み時に任意のヘッダを付ける
df = pd.read_csv("ファイル名", header=None, names=[名前1, 名前2, , ,名前n])
namesに与えるリストの要素数は、データの列数に合わせる - 例:1〜3行目にデータ以外のもの(データの説明など)が入っており、4行目がヘッダの場合
df = pd.read_csv("ファイル名", skiprows=[0, 1, 2])
- 例:1〜3行目にデータ以外のもの(データの説明など)が入っており、4行目からデータが入っている場合
df = pd.read_csv("ファイル名", skiprows=[0, 1, 2], header=None)
- 例:最初から50行を読み飛ばしたい場合
df = pd.read_csv("ファイル名", skiprows=50)
CSVファイルの時刻がparse_dates未対応の場合
日付データへの変換処理をdate_parserに関数で指定
import pandas as pd df = pd.read_csv("ファイル名", parse_dates=[0], index_col=[0], date_parser=parse_dates)parse_datesが関数名
- 例:時刻形式がGrADSで扱われる「00Z03FEB2020」のような形式の場合
from datetime import datetime def parse_dates(x): return datetime.strptime(x, "%HZ%d%b%Y") df = pd.read_csv("ファイル名", parse_dates=[0], index_col=[0], date_parser=parse_dates)
時刻表記の書式については時刻表記に用いられる書式指定子一覧参照 - 例:時刻形式が「2020/02/03 00:00」のような形式の場合
from datetime import datetime def parse_dates(x): return datetime.strptime(x, "%Y/%m/%d %H:%M") df = pd.read_csv("ファイル名", parse_dates=[0], index_col=[0], date_parser=parse_dates)
CSVファイルの列処理
- 例:読み込む列を指定する
import pandas as pd df = pd.read_csv("ファイル名", usecols=[0, 3])
1列目と4列目を読み込む - 例:経度データを−180〜180度ではなく0〜360度に
df = pd.read_csv("ファイル名", オプション) lons = np.array([l + 360. if l < 0 else l for l in df.loc[:, "longitude"]])
経度ラベルがlongitudeの場合
リスト内包表記で経度データを読み、0度より小さい場合に360度を足す
Numpyのndarrayに格納する(np.arrayをpd.SeriesにするとSeriesになる)
CSVファイルとして書き出す
pandasのDataFrameを使う場合
- DataFrameを書き出す
import pandas as pd pd.DataFrame(d).to_csv("ファイル名")
dはlistやnumpyのndarrayなど - indexを無効にしてから書き出す
pd.DataFrame(d).to_csv("ファイル名", index=False)
1列目に番号などが入らないファイルができる - ヘッダを付けない
pd.DataFrame(d).to_csv("ファイル名", header=False)
1行目にヘッダ行が入らないファイルができる - indexもヘッダも付けないこともできる
pd.DataFrame(d).to_csv("ファイル名", header=False, index=False)
データのみのファイルができる - カンマ区切りではなくタブ区切りで出力する(TSVファイルにする)
pd.DataFrame(d).to_csv("ファイル名", sep='\t')
sepで区切り文字をタブにする - 複数のndarrayからDataFrameを作成して書き出す
df = pd.DataFrame( { 'index': np.array(index), 'mean': np.array(dmean), 'std': np.array(dstd) }, dtype='float') df.to_csv("ファイル名")
indexは時刻データ、meanは平均値、stdは標準偏差の場合で、ヘッダ行ありで書き出す - CSVをbz2圧縮して書き出す
import bz2 df.to_csv("圧縮後のファイル.bz2", compression='bz2')
- CSVファイルの末尾に行を追記する
df.to_csv("ファイル名") # 新しいファイルを作成 df2.to_csv("ファイル名", mode='a', header=False) # 追記
mode='a'が追記を表す(デフォルトはmode='w'で、存在しない場合は新規作成、存在する場合は上書き)
追記する場合、CSVファイルの途中にヘッダが入らないようにheader=Falseとする
CSVデータの文字列を数値に変換する
文字列のまま一度書き出し、再読み込みを行うと数値データに変換される
- ファイルを利用する方法
df.to_csv("tmp.csv", index=False) df = pd.read_csv("tmp.csv")
dfはpandasのDataFrame - StringIOを利用する方法
from io import StringIO csv = df.to_csv(index=False) df = pd.read_csv(StringIO(csv))
行の読み飛ばしオプションにも対応(CSVファイルの行処理参照)
CSVファイル読み込み時のエラー
読み込み時にUnicodeDecodeErrorが出る場合(UTF-8でない場合には、文字化けではなくエラーとなる)
df = pd.read_csv("ファイル名", encoding='shift_jis')*WindowsのShift JISで読み込む
圧縮されたCSVファイルの読み込み
pd.read_csvのcompressionオプションは、デフォルトで'infer'なので、ファイルの拡張子を見て圧縮ファイルかどうか判断してくれる
df = pd.read_csv("ファイル名")具体的に圧縮形式を指定する場合、 pd.read_csvにcompressionオプションを付ける。
df = pd.read_csv("ファイル名", compression="bz2")*bz2で圧縮されたCSVファイルを読み込む
CSVファイルを圧縮して書き出し
pandasのDataFrameの書き出しの際にcompressionオプションを付ける
df.to_csv("ファイル名.gz", compression='gzip')*gzipで圧縮したCSVファイルを書き出す
TSVファイル
TSVファイルの形式
TSV(Tab-Separated Values)は、タブ区切りのテキストデータ
時刻<tab>項目<tab>項目2<tab>項目3 時刻1<tab>データ1-1<tab>データ1-2<tab>データ1-3 時刻2<tab>データ2-1<tab>データ2-2<tab>データ2-3 ...*<tab>は制御文字のHT(Horizontal Tabulation:水平タブ)を表す
TSVファイルの読み込み
pandasのread_csvにsepオプションを与える
- ヘッダ有りの場合
df = pd.read_csv("ファイル名", sep='\t')
CSVファイルのセパレータがタブであることを指定
ヘッダが列の名前になる - ヘッダ無しの場合
df = pd.read_csv("ファイル名", sep='\t', header=None)
- ヘッダ無しのファイルを読み込み列の名前を付ける場合
df = pd.read_csv("ファイル名", sep='\t', header=None, names=('列1の名前', '列2の名前'))
TSVファイルとして書き出す
pandasのDataFrameを使う場合
- DataFrameを書き出す
pd.DataFrame(d).to_csv("ファイル名", sep='\t')
dはlistやnumpyのndarrayなど - indexを無効にしてから書き出す
pd.DataFrame(d).to_csv("ファイル名", sep='\t', index=False)
1列目に番号などが入らないファイルができる - ヘッダを付けない
pd.DataFrame(d).to_csv("ファイル名", sep='\t', header=False)
1行目にヘッダ行が入らないファイルができる
LTSVファイル
TSVファイルの中には、Labeled Tab-separated Values(LTSV)形式のものがある
。各列にラベルを付けることで、データが欠損になった場合やデータが追加になった場合にも柔軟に対応できる。
- LTSV形式のファイルの形式
time:時刻1<tab> lat:緯度1<tab> lon:経度1<tab> t:気温1<tab> p:気圧1 time:時刻2<tab> lat:緯度2<tab> lon:経度2<tab> t:気温2<tab> p:気圧2 ...
- LTSV形式のファイルを読み込む
from collections import OrderedDict with open(path_to_file) as f: df = pd.DataFrame([ OrderedDict( cell.split(':', 1) for cell in line.rstrip('\r\n').split('\t')) for line in f ])
SSVファイル
SSVファイルの形式
SSV(Space-Separated Values)は、スペース区切りのテキストデータ
時刻 項目 項目2 項目3 時刻1 データ1-1 データ1-2 データ1-3 時刻2 データ2-1 データ2-2 データ2-3 ...
SSVファイルの読み込み
pandasのread_csvにsepオプションを与える
- ヘッダ有りの場合
df = pd.read_csv("ファイル名", sep='\s+')
CSVファイルのセパレータがスペース(連続する任意の文字数のスペース)であることを指定する
ヘッダが列の名前になる - ヘッダ無しの場合
df = pd.read_csv("ファイル名", sep='\s+', header=None)
- ヘッダ無しのファイルを読み込み列の名前を付ける場合
df = pd.read_csv("ファイル名", sep='\s+', header=None, names=('列1の名前', '列2の名前'))
- 固定長のSSVファイルの場合
df = pd.read_fwf("ファイル名")
個々のレコードが記述されている列が、ファイル全体で不変の場合 - ヘッダ無しの場合
df = pd.read_fwf("ファイル名", header=None)
SSVファイルとして書き出す
pandasのDataFrameを使う場合
- DataFrameを書き出す
pd.DataFrame(d).to_csv("ファイル名", sep=' ')
dはlistやnumpyのndarrayなど - indexを無効にしてから書き出す
pd.DataFrame(d).to_csv("ファイル名", sep=' ', index=False)
1列目に番号などが入らないファイルができる - ヘッダを付けない
pd.DataFrame(d).to_csv("ファイル名", sep=' ', header=False)
1行目にヘッダ行が入らないファイルができる
JSONファイル
JSONファイルの形式
データの名前(キー)とデータの組み合わせを決められたフォーマットで記述し、階層構造を持たせたテキストデータ
{"時刻1":{ {"キー1":"データ1"}, {"キー2":"データ2"}, {"キー3":["データ3-1","データ3-2","データ3-3"]}, ...}, "時刻2":{ {"キー1":"データ1"}, {"キー2":"データ2"}, {"キー3":["データ3-1","データ3-2","データ3-3"]}, ...}, ... }*時刻毎に複数のデータが入っている場合
JSONファイルの読み込み
- jsonモジュールを使う
import pandas as pd import json with open('ファイル名', 'rt') as fin: data = fin.read() df = pd.DataFrame(json.loads(data))
データの名前を指定する場合obj = json.loads(data) df = pd.DataFrame(obj['データ名'])
- Pandasで直接読み込み
import pandas as pd df = pd.read_json('ファイル名')
JSONファイルの書き出し
jsonモジュールを使う
import json d = ... with open('ファイル名', 'w') as fout: json.dump(d, fout) df = pd.DataFrame(json.loads(data))データの形式については、JSONファイルの形式参照
バイナリファイル
バイナリファイルの形式
ここでは、GrADS等で用いられる下記の形式の単純なバイナリファイルについて記載している。NumPy独自のバイナリ(npy、npz)とは異なる。
4バイト浮動小数点数(単精度)のデータや8バイト浮動小数点数(倍精度)のデータを改行コード無しで並べた単純バイナリ形式
4バイト浮動小数点数(単精度)のデータや8バイト浮動小数点数(倍精度)のデータを改行コード無しで並べた単純バイナリ形式
- 例:単精度で経度、緯度方向とも10度の等間隔データの場合
t=0: | 0E, 90N | 10E, 90N | ... | 350E, 90N | t=0: | 0E, 80N | 10E, 80N | ... | 350E, 80N | ... t=1: | 0E, 90S | 10E, 80N | ... | 350E, 80N | t=1: | 0E, 90N | 10E, 90N | ... | 350E, 90N | t=1: | 0E, 80N | 10E, 80N | ... | 350E, 80N | ... t=1: | 0E, 90S | 10E, 80N | ... | 350E, 80N |
| |で囲まれた部分がデータを表していて、1つのサイズが4バイト
バイナリファイルのエンディアン
エンディアン:2バイト以上のデータを保存する場合の保存順序の規則
ビックエンディアン(Big Endian)とリトルエンディアン(Little endian)の2種類
ビックエンディアン(Big Endian)とリトルエンディアン(Little endian)の2種類
- 例:4バイトの場合
データ:AABBCCDD ビックエンディアン:AABBCCDD(上位から保存) リトルエンディアン:DDCCBBAA(下位から保存)
バイナリファイルの読み込み
- Numpyを使った方法(先頭からdatasize分だけ読み込み)
import numpy as np endian = 'big' idim = 288 # 経度方向のサイズ(整数) jdim = 145 # 緯度方向のサイズ(整数) num_rec = 3 # データの個数(整数) datasize = idim * jdim * num_rec # 読み込むデータサイズ(個数) if endian == 'big': din = np.fromfile('読み込むファイル名', dtype='>f4', count=datasize) else: din = np.fromfile('読み込むファイル名', dtype='<f4', count=datasize) d = din.reshape(num_rec, jdim, idim)
ビックエンディアンの単精度(4バイト)浮動小数点数の場合がdtype='>f4'の書式に対応
リトルエンディアンの場合にはdtype='<f4'となる
書式の一覧はNumpyバイナリデータ読み書きの書式一覧参照 - arrayを使った方法(指定した時刻データを切り出す)
np.fromfileではメモリサイズ不足の場合などimport array import sys idim = 288 # 経度方向のサイズ(整数) jdim = 145 # 緯度方向のサイズ(整数) tsta = 5 # 開始データ番号(整数、データの先頭番号は1) tend = 7 # 終了データ番号(整数、データの先頭番号は1) datasize = idim * jdim # 水平方向のデータサイズ(個数) with open('読み込むファイル名', 'rb') as fin: fin.seek(4 * datasize * (tsta - 1), 0) # 開始データの前まで読み飛ばす(単位:byte) buf = array.array('f') # 4バイト浮動小数点数 buf.fromfile(fin, datasize * (tend - tsta + 1)) # データの読み込み if sys.byteorder == 'little': buf.byteswap() # bufからlistに変換し、x-, y-の配列に d = np.array(buf.tolist()).reshape(jdim, idim)
4バイト浮動小数点数の場合のarray書式('f')
sys.byteorderを使い、ビックエンディアンとリトルエンディアンを判定(システムがリトルエンディアンの場合にビックエンディアンとして読み込むようにしている)
ここではデータの先頭番号が1としているが、先頭番号を0としたい場合には、tsta - 1をtstaに、tend - tsta + 1をtend - tstaに変える
8バイト浮動小数点数の場合、array書式('d')となり、fin.seekで読み飛ばすサイズは8*datasize*レコード数(byte)、となる
バイナリファイルの書き出し
- Numpyを使った方法(ndarrayのメソッドを使って書き出す)
np.array(d).tofile("ファイル名")
dはlistやnumpyのndarray、pandasのDataFrameなど
書き出されるデータのエンディアンはマシン依存 - データの型を指定する場合
np.array(d).tofile("ファイル名", dtype=np.float32)
単精度(4バイト)浮動小数点型で書き出す場合 - データをbig endianで書き出す場合
np.array(d).astype('>f4').tofile("ファイル名")
- データをlittle endianで書き出す場合
np.array(d).astype('<f4').tofile("ファイル名")
- データを倍精度(8バイト)浮動小数点型のlittle endianで書き出す場合
np.array(d).astype('<f8').tofile("ファイル名")
書式の一覧はNumpyバイナリデータ読み書きの書式一覧参照
Numpy独自のバイナリファイル
Numpy独自のバイナリファイルの形式
Numpyでは、内部で使われている配列ndarrayをNumpy独自のバイナリファイル(npy、npz)として保存できる。配列のデータ型や形状を保持でき、npyでは1つの配列、npzでは複数の配列を保存できる。このバイナリ形式はNumpy独自であり機種依存性もあるため、基本的には同じマシンでNumpyを利用して読み書きを行う。
Numpy独自のバイナリファイルの読み書き
モジュールをインポートする
import numpy as np
- Numpyを使って読み込む(npy、npz共通)
d = np.load('ファイルへのパス')
- Numpyを使って書き出す(npy)
np.save('ファイルへのパス', d)
*dは配列ndarray - Numpyを使って書き出す(npz)
np.savez('ファイルへのパス', d1, d2)
*d1, d2は配列ndarray - Numpyを使って書き出す(npz、キーワードあり)
np.savez('ファイルへのパス', data=d, lons=lons, lats=lats)
*d、lons、latsは配列ndarray - Numpyを使って書き出す(npz、キーワードあり、圧縮)
np.savez_compressed('ファイルへのパス', data=d, lons=lons, lats=lats)
- Numpyを使って読み込む(npz、キーワードあり)
d = np.load('ファイルへのパス') lons = d['lons'] lats = d['lats'] data = d['data']
*lons、lats、dataに保存した配列が入る
NetCDFファイル
NetCDFファイルの形式
NetCDFファイルには、データと一緒に格子点の情報やデータの説明も一緒に格納されている。データの説明も格納できるため、データを作成したモデルの名前や作成者、変数の導出方法、参照元の文献やURL などを記述しておけば、利用者がデータの中身を理解しやすい。また、格納されたデータを機種に依存することなく取り出せるため、データの配布に適している。
NetCDFのモジュール
モジュールをインポートする
インポートでエラーが出る場合
import netCDF4
インポートでエラーが出る場合
- MacPortsでpython3.11のnetcdfライブラリをインストール
% sudo port install py311-netcdf4
*pythonのバージョンが異なる場合には、py311の部分を対応するものに変える
*HomebrewやAnacondaを使っている場合には、競合を避けるためMacPortsは使わない方が良い
NetCDFファイルの読み込み
NetCDFファイルに含まれている変数名などを確認する
% ncdump -h ファイル名ファイルを開き、指定した変数名のデータを取り出す
nc = netCDF4.Dataset('ファイル名', 'r') var = nc.variables['変数名'][:]
- 例:SLPデータの読み込み(変数名slpの場合)
nc = netCDF4.Dataset('ファイル名', 'r') var = nc.variables['slp'][:]
- 例:軸情報の読み込み
lon = nc.variables["lon"][:] # 経度 lat = nc.variables["lat"][:] # 緯度 time = nc.variables["time"][:] # 時刻
NetCDFファイル情報の取得
nc = netCDF4.Dataset('ファイル名', 'r') idim = len(nc.dimensions['lon']) # 経度方向のデータ数 jdim = len(nc.dimensions['lat']) # 緯度方向のデータ数 ndim = len(nc.dimensions['time']) # 時間方向のデータ数 add_offset = nc.variables['変数名'].add_offset # データのオフセット scale_factor = nc.variables['変数名'].scale_factor # データのスケールファクター
データにスケールファクターとオフセットがある場合
nc = netCDF4.Dataset('ファイル名', 'r') var_i = nc.variables['変数名'][:] add_offset = nc.variables['変数名'].add_offset scale_factor = nc.variables['変数名'].scale_factor var = var_i * scale_factor + add_offset
変数がグループ化されている場合
グループ化されている場合、
% ncdump -h ファイル名でvariablesの上位にgroupが表示される。その場合、groupの下位に表示される変数名(ここでは変数名1、変数名2があるものとする)を使い、以下のように取り出す
nc = netCDF4.Dataset('ファイル名', 'r') grp = nc.groups['グループ名'] var1 = grp.variables['変数名1'][:] var2 = grp.variables['変数名2'][:]
GRIB2ファイル
GRIB2ファイルの形式
WMOが定めたバイナリデータの交換形式のうち、2001年に制定された第2版を指す。後述のGRIB1形式とは互換性がない。格納されたデータを機種に依存することなく取り出すことができ、データと一緒に格子点の情報や変数の簡単な説明等も格納できる。詳細についてはQiitaの記事に詳しい。
GRIB2ファイルの読み込み
GRIB2ファイルの読み込みを行うには、まずGRIB2からNetCDFへ変換し、NetCDFとして読み込む方法が良い。変換にはwgrib2を用いる。MacPortsであれば、
*wgrib2のバージョン3.1.2ではJPEG2000のエラーが発生するデータが存在する。バージョン3.1.3では解消された。
% sudo port install wgrib2で導入できる。wgrib2を用いて次のように変換する。
% wgrib2 入力ファイル名 -netcdf 出力ファイル名変換後のファイルは、NetCDFに記述した方法で読み込み可能
*wgrib2のバージョン3.1.2ではJPEG2000のエラーが発生するデータが存在する。バージョン3.1.3では解消された。
pygribを使ったGRIB2ファイルの読み込み
pygribモジュールを用いると、直接GRIB2ファイルを読み込むことができた。
*MacPortsでは、python3.11以降のpygribが提供されていない。
% sudo port install py310-pygribで導入できる(python3.10の場合。異なるバージョンではpy310の部分を変える)。pygribでは次のようにデータを取り出す。
import pygrib grbs = pygrib.open("ファイル名") # GRIB2ファイルを開く grb1 = grbs.select(forecastTime=1)[0] # 1時間後の0番目の変数 grbt = grbs.select(name="Temperature") # 気温の変数を選択ファイルの読み込みに時間がかかるため、読み込み処理が多い場合にはGRIB2ファイルの読み込みに記述した方法に切り替えた方が良い。
*MacPortsでは、python3.11以降のpygribが提供されていない。
wgrib2による単純バイナリファイルへの変換
wgrib2コマンドを使うと、単純バイナリファイルに変換可能。変換したファイルの読み込み方法はバイナリファイルの読み込み参照。北極が先、下層が先に入ったビックエンディアンの単純バイナリファイルに変換する場合
*-order we:nsで、西から東、北から南の順に並べ替えて出力
*下層が先になるように、sort -nr -k5 -t':'で並べ替えを行っている
*最初のwgrib2は、ファイルの中に含まれる変数をリスト化するためのもので、2回目のwgrib2は、リストを読み込んで入力ファイルからリストに対応するデータをファイルに書き出すためのもの。grepやsortでリストのうち必要な変数の取り出しや並べ替えを行う。
*追加書き込みを行う際には、wgrib2 入力ファイル.grb -i -no_header -append -order we:ns -ieee -o 出力ファイル.bin
% wgrib2 -v 入力ファイル.grb | grep "変数名" | grep "時刻" | sort -nr -k5 -t':' \ | wgrib2 入力ファイル.grb -i -no_header -order we:ns -ieee -o 出力ファイル.bin*-no_headerはヘッダ無し、-ieeeはビックエンディアン
*-order we:nsで、西から東、北から南の順に並べ替えて出力
*下層が先になるように、sort -nr -k5 -t':'で並べ替えを行っている
*最初のwgrib2は、ファイルの中に含まれる変数をリスト化するためのもので、2回目のwgrib2は、リストを読み込んで入力ファイルからリストに対応するデータをファイルに書き出すためのもの。grepやsortでリストのうち必要な変数の取り出しや並べ替えを行う。
*追加書き込みを行う際には、wgrib2 入力ファイル.grb -i -no_header -append -order we:ns -ieee -o 出力ファイル.bin
GRIB1ファイル
GRIB1ファイルの形式
WMOが定めたバイナリデータの交換形式のうち、1989年に制定された第1版を指す。前述のGRIB2形式とは互換性がない。格納されたデータを機種に依存することなく取り出せ、データと一緒に格子点の情報や変数の簡単な説明等も格納できる。
GRIB1ファイルの読み込み
GRIB1形式は、pythonで直接読むことはできないが、GrADSに付属しているwgribコマンドを使うことで、単純バイナリファイルに変換可能。変換したファイルの読み込み方法はバイナリファイルの読み込み参照。JRA-55客観解析データの気圧面データを使い、下層が先に入ったビックエンディアンの単純バイナリファイルに変換する場合
*下層が先になるように、sort -nr -k5 -t':'で並べ替えを行っている
*最初のwgribは、ファイルの中に含まれる変数をリスト化するためのもので、2回目のwgribは、リストを読み込んで入力ファイルからリストに対応するデータをファイルに書き出すためのもの。grepやsortでリストのうち必要な変数の取り出しや並べ替えを行う。
*追加書き込みを行う際には、wgrib -i -nh -ieee -append 入力ファイル.grb 出力ファイル.bin
% wgrib -v 入力ファイル.grb | grep ":GRIBIDを記述," | sort -nr -k5 -t':' \ | wgrib -i -nh -ieee 入力ファイル.grb -o 出力ファイル.bin*-nhはヘッダ無し、-ieeeはビックエンディアン
*下層が先になるように、sort -nr -k5 -t':'で並べ替えを行っている
*最初のwgribは、ファイルの中に含まれる変数をリスト化するためのもので、2回目のwgribは、リストを読み込んで入力ファイルからリストに対応するデータをファイルに書き出すためのもの。grepやsortでリストのうち必要な変数の取り出しや並べ替えを行う。
*追加書き込みを行う際には、wgrib -i -nh -ieee -append 入力ファイル.grb 出力ファイル.bin
HDF5ファイル
HDF5ファイルの形式
HDF形式は、米国立スーパーコンピュータ応用研究所(National Center for Supercomputing Applications:NCSA)で開発され、大量のデータを格納し構造化するために設計されている。データと一緒に格子点の情報や変数の説明なども格納することができ、格納されたデータを機種に依存することなく取り出せる。HDF形式には、古いHDF4形式と新しいHDF5形式があり、両者に互換性はない。HDF5はファイル構造が単純化されており、ディレクトリに相当するグループとファイルに相当するデータセットの2種類で階層構造を持って保存することができる。
HDF5ファイルの読み込み
Pythonでは、Pandasやh5pyでHDF5ファイルを読むことができる。Pandasで読み込めない形式の場合にはh5pyを使う。
- 例:Pandasを使った方法
import pandas as pd df = pd.read_hdf("ファイル名")
- 例:h5pyを使った方法
Python3.11の場合、MacPortsを使い次のようにインストール(バージョンが異なる場合はpy311の部分を変える)% sudo port install py311-h5py
2次元データをdに格納する場合import h5py hdf = h5py.File("ファイル名", "r") # HDF5ファイルを開く d = hdf['データセットの名前'][:, :] # データセットの名前に対応するデータを取得
*以前はhdf['データセットの名前'].valueを使うことができたが、現在のバージョンではエラーが出る。
*データセットの名前を表示したい場合には、print(hdf.keys())
GTOOL3ファイル
GTOOL3ファイルの形式
GTOOL3形式は、気候モデルMIROCの出力に用いられているバイナリ形式で、ヘッダ部とデータ部のセットで構成され改行コードで区切られている。ヘッダ部にはデータ部の格納形式(例えば、1レコードが4バイトか8バイトか)やサイズ、欠損値、日時などが16 文字×64欄の文字データとして格納されている。また、データの経度、緯度、高度方向の格子点数や、格子点値が記述された格子情報ファイル名なども格納され、データの名前、作成 、作成日時なども記述することができる。データ部は単純バイナリで、ビックエンディアン、リトルエンディアンどちらも許容されており、機種依存性がある。
- GTOOL3ファイルの形式
t=0:| ヘッダ部(16 文字×64欄)| 改行コード t=0:| データ部 | 改行コード t=1:| ヘッダ部(16 文字×64欄)| 改行コード t=1:| データ部 | 改行コード ...
| |で囲まれた部分がヘッダ部やデータ部を表す。
GTOOL3ファイルの読み込み
GTOOL3の読み込みには、gtool3更新版を用いることができる。
*変数名や次元はgt.varsで表示できる。
*気候モデルのMIROCの出力を用いた処理方法は、PythonでGTOOL3ファイルを処理するに詳しい。
from gtool3 import gtopen gt = gtopen("ファイル名") # GTOOL3ファイルを開く d = gt['変数名'][:, :, :, :] # 変数名に対応するデータ取得(次元はデータに合わせる)*時刻、高度、緯度、経度が入ったデータの場合
*変数名や次元はgt.varsで表示できる。
*気候モデルのMIROCの出力を用いた処理方法は、PythonでGTOOL3ファイルを処理するに詳しい。
画像ファイル
画像ファイルの読み込み(Pillow)
ここでは、様々な画像フォーマットに対応しているPillowを利用した読み込み方法を紹介する。Pillowでは、PNG、BMP、GIF、JPEG、TIFF、EPSなど、主要な形式の読み書きに対応している。読み込む場合には、
from PIL import Image im = Image.open("画像ファイルのパス")Numpyで扱う場合には、次のようにndarrayに変換する
im = np.asarray(im)urllibを利用して、web上の画像を読み込むことも可能
from PIL import Image import urllib.request im = Image.open(urllib.request.urlopen("URLを指定"))
画像ファイルの書き出し(Pillow)
Pillowで書き出す場合には、
im.save("画像ファイル名")書き出す画像の質を指定する場合(jpg)、
im.save("画像ファイル名.jpg", quality=95)
読み込んだ画像の処理(Pillow)
Pillowの機能としてグレースケール変換、切り出し、サイズの変更などが可能。
[top] - グレースケール変換
from PIL import Image im = Image.open("画像ファイルのパス") im_gray = im.convert('L') # グレースケールに変換
- 切り出し
im = im.crop((0, 50, 600, 300))
座標は(left, upper, right, lower)で指定する
tupleで与えるので、括弧が2重になっている - サイズの変更
im = im.resize((128, 128))
128x128ピクセルに変換する - サイズの変更(手法の指定)
im = im.resize((128, 128), Image.LANCZOS)
LANCZOSフィルターを用いる
デフォルトはNEARESTフィルター
NEAREST、BOX、BILINEAR、HAMMING、BICUBIC、LANCZOSが指定可能(後のものほど高品質で処理時間かかる) - 画像の回転
im = im.rotate(90))
90度回転する - カラー画像のRGB成分を取り出す
r, g, b = im.split()
- 取り出したRGB成分をBRGに入れ替える
im = Image.merge("RGB", (b, r, g))