Yuta NakataのBlog

Python / AWS / ITについて役立つ情報を発信します

netcdfファイルを軽量化する方法

背景

netCDFは、多次元データを格納するのに便利な拡張子です。

気象、海洋、気候の世界では広く使われています。

一方で、このデータの課題として、多次元配列が故にファイルサイズが大きくなることが挙げられます。

これにより、データの読み込み時にメモリの使用量が増え、かつ待機時間が伸びることが課題になりがちです。

そこで、今回はnetcdfのファイルサイズを圧縮する方法をお伝えします。

結論

xarrayライブラリを使います。

公式Documentは以下の通りです。

docs.xarray.dev

print(ds)
"""
<xarray.Dataset> Size: 416B
Dimensions:        (loc: 2, instrument: 3, time: 4)
Coordinates:
    lon            (loc) float64 16B -99.83 -99.32
    lat            (loc) float64 16B 42.25 42.21
Dimensions without coordinates: loc, instrument, time
Data variables:
    temperature    (loc, instrument, time) float64 192B 9.584 18.36 ... 16.99
    precipitation  (loc, instrument, time) float64 192B 4.323 8.643 ... 1.573
Attributes:
    description:  Weather related data.
"""
ds.to_netcdf("output.nc", encoding={'temperature':{'dtype': 'int16', "zlib": True, , "complevel": 9}}})

Pointは、

  • encodingで、zlib=Trueにすること。
  • 型を与えて不必要以上の型を与えないこと。
  • floatは、スケールファクターを与えてint型で保存すると効果はバツグン

です。

軽量化したファイルの書き込み

上記のとおりです。

公式Documentを見ながら、試してみてください。

docs.xarray.dev

軽量化したファイルの読み込み

特に変化はありません。

import xarray as xr

file = "NC_H08_20161117_0230_B01_JP02_R10.nc"

ds = xr.open_dataset(file)

サンプルデータ

www.data.jma.go.jp

xarrayでデータを作る

書き込みが想定されるので、データの作り方も合わせて例示します。

import numpy as np
import pandas as pd
import xarray as xr


temperature = 15 + 8 * np.random.randn(2, 3, 4)
precipitation = 10 * np.random.rand(2, 3, 4)
lon = [-99.83, -99.32]
lat = [42.25, 42.21]
instruments = ["manufac1", "manufac2", "manufac3"]
time = pd.date_range("2014-09-06", periods=4)
reference_time = pd.Timestamp("2014-09-05")

ds = xr.Dataset(
    data_vars=dict(
        temperature=(["loc", "instrument", "time"], temperature),
        precipitation=(["loc", "instrument", "time"], precipitation),
    ),
    coords=dict(
        lon=("loc", lon),
        lat=("loc", lat),
    ),
    attrs=dict(description="Weather related data.")
)
print(ds)

ナウでヤングな方法は、netcdf4からxarrayかもしれない(?)