h5py について
h5pyは、NumPyとHDF5をつなぎ、大規模な数値データセットを整理・取得するPythonライブラリです。階層型ストレージ、メタデータ、必要な部分だけの読み込みを求める科学・データ処理に適しています。
主な機能
- 01グループとデータセットの階層管理
- 02NumPy形式のスライス
- 03オブジェクトごとのメタデータ属性
- 04チャンク化と圧縮保存
- 05サイズ変更可能なデータセット
活用シーン
- 01利用可能なメモリを超える配列の保存
- 02科学データとメタデータの整理
- 03大容量ファイルから必要な領域を読み込み
- 04シミュレーションデータの継続的な追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tondevrel/ scientific-agent-skills --skill h5pyインストール後、Claude Code で/h5pyを入力して読み込まれたか確認します。
詳細
h5py - 階層型データストレージ
h5py は NumPy と HDF5 の間をシームレスにつなぎます。データをグループ(フォルダーのようなもの)やデータセット(NumPy 配列のようなもの)に整理し、各オブジェクトに豊富なメタデータ(属性)を付与できます。
使用する場面
- コンピューターの RAM よりもはるかに大きなデータセットを保存する場合。
- 複雑な科学データを階層的な「フォルダーのような」構造に整理する場合。
- 高速なランダムアクセスが可能な数値配列(NumPy)を保存する場合。
- メタデータ(単位、実験日、パラメーター)をデータに直接付与して保持する場合。
- HDF5 はクロスプラットフォーム標準であるため、異なる言語(C、C++、Fortran、Java、MATLAB)間でデータを共有する場合。
- I/O パフォーマンスを最適化するため、大規模なデータセットをチャンク単位で読み書きする場合。
リファレンスドキュメント
公式ドキュメント:https://docs.h5py.org/
HDF Group:https://www.hdfgroup.org/
検索パターン:h5py.File、create_dataset、h5py.Group、chunks=True、compression="gzip"
基本原則
階層構造
HDF5 ファイルには、主に次の 2 種類のオブジェクトが含まれます。
- データセット:データの多次元配列(NumPy に似たもの)。
- グループ:データセットや他のグループを格納できるコンテナー構造(ディレクトリのようなもの)。
スライス
h5py のデータセットは、標準的な NumPy のスライスに対応しています。データセットをスライスすると、指定した範囲だけがディスクから読み込まれるため、メモリ使用量を抑えられます。
属性
すべてのグループとデータセットには、メタデータ用の属性(キーと値のペア)を設定できます。
クイックリファレンス
インストール
pip install h5py
標準的なインポート
import h5py
import numpy as np
基本パターン - 書き込みと読み込み
import h5py
import numpy as np
# Writing data
with h5py.File('data.h5', 'w') as f:
dset = f.create_dataset('main_data', data=np.random.rand(100, 100))
dset.attrs['units'] = 'meters'
grp = f.create_group('subgroup')
grp.create_dataset('results', data=[1, 2, 3])
# Reading data
with h5py.File('data.h5', 'r') as f:
data_slice = f['main_data'][0:10, 0:10] # Only read 100 elements
units = f['main_data'].attrs['units']
print(f"Group content: {list(f['subgroup'].keys())}")
重要なルール
✅ 推奨事項
- コンテキストマネージャーを使用する - エラーが発生した場合でもファイルが確実に閉じられるよう、常に
with h5py.File(...) as f:を使用します。 - チャンク化を使用する - 大規模なデータセットでは、特定のスライスパターンでのアクセス速度を最適化するため、
chunks=Trueまたは手動で指定した形状を指定します。 - 圧縮を有効にする - 大規模な数値配列のディスク容量を節約するには、
compression="gzip"を使用します。 - わかりやすい名前を使用する - グループを使ってデータを論理的に整理します(例:
/experiment1/sensorA/raw)。 - 属性にメタデータを保存する - 単位やタイムスタンプ用に別のテキストファイルを作成せず、データセットに付与します。
- メンバーシップを確認する - KeyError を避けるため、アクセスする前に
"name" in groupを使用します。
❌ 禁止事項
- 誤って 'w' モードでファイルを開く - 'w' モードは既存のファイルを上書きします。代わりに 'a'(追記/読み書き)または 'r+'(読み書き)を使用します。
- データセット全体を RAM に読み込む - メモリに収まると確信できない限り、
data = f['large_dataset'][:]は避けます。 - 何千もの小さなデータセットを保存する - HDF5 は大規模な配列向けに最適化されています。小さなスカラーが数百万個ある場合は、1 つの配列または別のデータベースを使用します。
- ファイルを閉じ忘れる - HDF5 ファイルを閉じないままにすると、破損したりロックされたりする可能性があります。
アンチパターン(絶対に避ける)
import h5py
import numpy as np
# ❌ BAD: Manual file closing (unsafe)
f = h5py.File('data.h5', 'w')
f.create_dataset('x', data=np.arange(10))
f.close() # If an error happened above, this never runs!
# ✅ GOOD: Context manager
with h5py.File('data.h5', 'w') as f:
f.create_dataset('x', data=np.arange(10))
# ❌ BAD: Storing metadata as strings inside a dataset
f.create_dataset('meta', data=np.array(['unit: meter', 'date: 2024']))
# ✅ GOOD: Using Attributes
dset = f.create_dataset('data', data=np.random.rand(10))
dset.attrs['unit'] = 'meter'
dset.attrs['date'] = '2024'
# ❌ BAD: Inefficient chunking (one row at a time when you read columns)
# f.create_dataset('big', shape=(10000, 10000), chunks=(1, 10000))
データセットの作成と設定
高度なオプション
with h5py.File('optimized.h5', 'w') as f:
# 1. Resizable dataset (maxshape)
dset = f.create_dataset('growing',
shape=(100,),
maxshape=(None,), # Allow growth in 1st dimension
dtype='float32')
# 2. Compression and Chunking
f.create_dataset('compressed',
data=np.random.randn(1000, 1000),
chunks=(100, 100),
compression="gzip",
compression_opts=4) # 4 is a good balance
# 3. Filling with default values
f.create_dataset('default', shape=(10, 10), fillvalue=-1.0)
グループの操作
移動と反復処理
with h5py.File('nested.h5', 'w') as f:
f.create_group('raw/2024/january')
f.create_group('raw/2024/february')
# Recursive iteration
def print_structure(name, obj):
print(name)
with h5py.File('nested.h5', 'r') as f:
f.visititems(print_structure) # Visits every dataset and group
# Accessing via path
feb_data = f['/raw/2024/february']
パフォーマンスの最適化
1. チャンク化の戦略
チャンクは、読み書きできる最小単位のデータです。
- 通常、行ごとに読み込む場合:
chunks=(1, n_cols)。 - ブロック単位で読み込む場合:
chunks=(100, 100)。 - よくわからない場合:
chunks=Trueを指定すると、h5py が推定します。
2. SWMR(単一書き込み・複数読み込み)
他のプロセスがリアルタイムでファイルを読み込んでいる間に、書き込み側がファイルに追記できるようにします。
# Writer
f = h5py.File('live.h5', 'w', libver='latest')
f.swmr_mode = True
# Reader
f = h5py.File('live.h5', 'r', libver='latest', swmr=True)
3. Core ドライバー(メモリ内 HDF5)
HDF5 の構造を使用しながら、速度を高めるためにデータ全体を RAM に保持します。必要に応じてディスクに保存することもできます。
# Create an HDF5 file in memory
f = h5py.File('memfile.h5', 'w', driver='core', backing_store=True)
実践的なワークフロー
1. 機械学習の訓練データの保存
def save_ml_dataset(X, y, filename):
with h5py.File(filename, 'w') as f:
# Create datasets for images and labels
f.create_dataset('images', data=X, compression="lzf") # LZF is fast
f.create_dataset('labels', data=y)
# Add metadata
f.attrs['n_samples'] = X.shape[0]
f.attrs['input_shape'] = X.shape[1:]
f.attrs['classes'] = np.unique(y)
# Use cases: training on data that exceeds RAM
2. 大規模シミュレーションのロガー
def log_simulation_step(filename, step_idx, data_array):
with h5py.File(filename, 'a') as f:
if 'simulation' not in f:
# Initialize resizable dataset
f.create_dataset('simulation',
shape=(0, *data_array.shape),
maxshape=(None, *data_array.shape),
chunks=(1, *data_array.shape))
dset = f['simulation']
dset.resize(step_idx + 1, axis=0)
dset[step_idx] = data_array
3. 画像のバッチ保存
def store_images(image_files, h5_file):
with h5py.File(h5_file, 'w') as f:
grp = f.create_group('microscopy_data')
for i, img_path in enumerate(image_files):
# Load your image here
img_data = np.random.rand(512, 512)
dset = grp.create_dataset(f'img_{i:04d}', data=img_data)
dset.attrs['original_path'] = img_path
よくある問題と解決策
「データセットはすでに存在します」エラー
# ❌ Problem: f.create_dataset('x', ...) fails if 'x' exists
# ✅ Solution: Delete first or use a check
if 'x' in f:
del f['x']
f.create_dataset('x', data=new_data)
ファイルロックの問題
# ❌ Problem: "OSError: Unable to open file (file locking disabled on this file system)"
# This often happens on network drives (NFS).
# ✅ Solution: Set environment variable before running script
import os
os.environ['HDF5_USE_FILE_LOCKING'] = 'FALSE'
import h5py
Unicode 文字列の保存
HDF5 の文字列サポートは複雑です。
# ❌ Problem: Storing lists of strings can sometimes cause issues in older versions
# ✅ Solution: Use special string types
dt = h5py.string_dtype(encoding='utf-8')
dset = f.create_dataset('strings', (100,), dtype=dt)
dset[0] = "Научные данные"
h5py は、大規模な数値データを扱うための堅牢な方法です。NumPy の柔軟性と HDF5 のパワーを組み合わせることで、科学データを整理された状態で保ち、アクセスしやすく、高速に利用できます。