NumPy配列をnpy・npzファイルで保存・読み込みする方法

フリーランスボード

20万件以上の案件から、副業に最適なリモート・週3〜の案件を一括検索できるプラットフォーム。プロフィール登録でAIスカウトが自動的にマッチング案件を提案。市場統計や単価相場、エージェントの口コミも無料で閲覧可能なため、本業を続けながら効率的に高単価の副業案件を探せます。フリーランスボード

ITプロパートナーズ

週2〜3日から働ける柔軟な案件が業界トップクラスの豊富さを誇るフリーランスエージェント。エンド直契約のため高単価で、週3日稼働でも十分な報酬を得られます。リモートや時間フレキシブルな案件も多数。スタートアップ・ベンチャー中心で、トレンド技術を使った魅力的な案件が揃っています。専属エージェントが案件紹介から契約交渉までサポート。利用企業2,000社以上の実績。ITプロパートナーズ

Midworks 10,000件以上の案件を保有し、週3日〜・フルリモートなど柔軟な働き方に対応。高単価案件が豊富で、報酬保障制度(60%)や保険料負担(50%)など正社員並みの手厚い福利厚生が特徴。通勤交通費(月3万円)、スキルアップ費用(月1万円)の支給に加え、リロクラブ・freeeが無料利用可能。非公開案件80%以上、支払いサイト20日で安心して稼働できます。Midworks

NumPy配列を効率的に保存・読み込みするには、バイナリファイル形式(npy、npz)の活用が重要です。本記事では、np.save()、np.load()、np.savez()などの関数を使った実践的な保存・読み込み方法を詳しく解説します。

NumPyバイナリファイル形式の基本

NumPyは配列データを効率的に保存するための専用バイナリ形式を提供しています。

ファイル形式の種類:

  • .npy: 単一配列の保存(非圧縮)
  • .npz: 複数配列の保存(圧縮・非圧縮対応)

バイナリ保存の利点:

  • CSVやテキストファイルより高速
  • データ型情報が完全に保持される
  • ファイルサイズが小さい
  • 多次元配列の構造が保持される

単一配列の保存・読み込み(.npyファイル)

1. 基本的な保存と読み込み

import numpy as np

# 配列の作成
data = np.array([1, 2, 3, 4, 5])

# .npyファイルに保存
np.save('data.npy', data)

# ファイルから読み込み
loaded_data = np.load('data.npy')
print(loaded_data)  # [1 2 3 4 5]

2. 多次元配列の保存

# 2次元配列の保存
matrix = np.array([[1, 2, 3], [4, 5, 6]])
np.save('matrix.npy', matrix)

# 読み込みと確認
loaded_matrix = np.load('matrix.npy')
print(loaded_matrix.shape)  # (2, 3)
print(loaded_matrix)

3. 異なるデータ型の保存

# float型配列の保存
float_array = np.array([1.1, 2.2, 3.3], dtype=np.float32)
np.save('float_data.npy', float_array)

# 読み込み時にデータ型が保持される
loaded_float = np.load('float_data.npy')
print(loaded_float.dtype)  # float32

複数配列の保存・読み込み(.npzファイル)

1. 複数配列の非圧縮保存

# 複数の配列を作成
arr1 = np.array([1, 2, 3])
arr2 = np.array([[4, 5], [6, 7]])
arr3 = np.array([8.1, 9.2, 10.3])

# 複数配列を.npzファイルに保存
np.savez('multiple_arrays.npz', 
         array1=arr1, array2=arr2, array3=arr3)

# 読み込み
loaded = np.load('multiple_arrays.npz')
print(loaded['array1'])  # [1 2 3]
print(loaded['array2'])  # [[4 5] [6 7]]

2. 圧縮保存(推奨)

# 圧縮して保存(ファイルサイズ削減)
np.savez_compressed('compressed_data.npz',
                    data1=arr1, data2=arr2)

# 読み込み方法は同じ
compressed_data = np.load('compressed_data.npz')
print(compressed_data['data1'])

3. 配列名を指定しない保存

# 配列名を省略して保存
np.savez('unnamed_arrays.npz', arr1, arr2, arr3)

# デフォルト名で読み込み
unnamed_data = np.load('unnamed_arrays.npz')
print(unnamed_data['arr_0'])  # arr1の内容
print(unnamed_data['arr_1'])  # arr2の内容

実践的なサンプルコード

サンプル1: 機械学習データの保存

import numpy as np

# 訓練データとラベルの作成
X_train = np.random.randn(1000, 10)  # 特徴量
y_train = np.random.randint(0, 2, 1000)  # ラベル
X_test = np.random.randn(200, 10)
y_test = np.random.randint(0, 2, 200)

# 機械学習データセットとして保存
np.savez_compressed('ml_dataset.npz',
                    X_train=X_train, y_train=y_train,
                    X_test=X_test, y_test=y_test)

# データセットの読み込み
dataset = np.load('ml_dataset.npz')
print("訓練データ形状:", dataset['X_train'].shape)
print("テストラベル:", dataset['y_test'][:5])

サンプル2: 時系列データの保存

# 時系列データの作成
dates = np.arange('2024-01', '2024-12', dtype='datetime64[M]')
sales = np.random.randint(100, 1000, len(dates))
profit = sales * 0.2 + np.random.randn(len(dates)) * 10

# 時系列データとして保存
np.savez('timeseries_data.npz',
         dates=dates, sales=sales, profit=profit)

# 読み込みと確認
ts_data = np.load('timeseries_data.npz')
print("期間:", ts_data['dates'][:3])
print("売上:", ts_data['sales'][:3])

サンプル3: 画像データの保存

# 簡単な画像データ(グレースケール)
image_data = np.random.randint(0, 256, (100, 100), dtype=np.uint8)
labels = np.array(['cat', 'dog', 'bird'])

# 画像データの保存
np.save('image_data.npy', image_data)
np.savez('image_dataset.npz', 
         images=image_data, labels=labels)

# 読み込み
loaded_image = np.load('image_data.npy')
print("画像サイズ:", loaded_image.shape)
print("データ型:", loaded_image.dtype)

ファイル操作とエラーハンドリング

1. ファイル存在確認

import os

def safe_load_npy(filename):
    """安全な.npyファイル読み込み"""
    if os.path.exists(filename):
        return np.load(filename)
    else:
        print(f"ファイル {filename} が見つかりません")
        return None

# 使用例
data = safe_load_npy('data.npy')
if data is not None:
    print("データ読み込み成功")

2. .npzファイルの内容確認

# .npzファイルの中身を確認
def inspect_npz(filename):
    """npzファイルの内容を表示"""
    try:
        data = np.load(filename)
        print(f"ファイル: {filename}")
        print(f"配列数: {len(data.files)}")
        for name in data.files:
            arr = data[name]
            print(f"  {name}: {arr.shape}, {arr.dtype}")
        data.close()
    except Exception as e:
        print(f"エラー: {e}")

# 使用例
inspect_npz('multiple_arrays.npz')

3. 大容量ファイルの効率的な処理

# メモリマップを使用した大容量ファイル処理
large_array = np.random.randn(10000, 1000)
np.save('large_data.npy', large_array)

# メモリマップで読み込み(メモリ効率的)
mmap_data = np.load('large_data.npy', mmap_mode='r')
print("一部データ:", mmap_data[0, :5])
print("メモリマップ使用")

パフォーマンス最適化

1. 圧縮率の比較

import os

# 同じデータを異なる方法で保存
test_data = np.random.randn(1000, 1000)

# 非圧縮
np.save('uncompressed.npy', test_data)
np.savez('uncompressed.npz', data=test_data)

# 圧縮
np.savez_compressed('compressed.npz', data=test_data)

# ファイルサイズの比較
print("npy:", os.path.getsize('uncompressed.npy'), "bytes")
print("npz:", os.path.getsize('uncompressed.npz'), "bytes")
print("圧縮npz:", os.path.getsize('compressed.npz'), "bytes")

2. 読み込み速度の最適化

import time

def benchmark_loading(filename, iterations=5):
    """読み込み速度のベンチマーク"""
    times = []
    for _ in range(iterations):
        start = time.time()
        data = np.load(filename)
        if hasattr(data, 'close'):
            data.close()
        times.append(time.time() - start)
    
    avg_time = np.mean(times)
    print(f"{filename}: 平均読み込み時間 {avg_time:.4f}秒")

# 使用例
benchmark_loading('uncompressed.npy')
benchmark_loading('compressed.npz')

高度な活用方法

1. 配列のバックアップとバージョン管理

from datetime import datetime

def save_with_timestamp(data, base_name):
    """タイムスタンプ付きで保存"""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = f"{base_name}_{timestamp}.npy"
    np.save(filename, data)
    print(f"保存完了: {filename}")
    return filename

# 使用例
important_data = np.random.randn(100, 100)
backup_file = save_with_timestamp(important_data, 'backup')

2. 配列の部分的な更新

# 大きな配列の一部のみを更新
def update_array_section(filename, new_data, start_idx):
    """配列の一部を更新"""
    # 既存データを読み込み
    existing = np.load(filename)
    
    # 一部を更新
    updated = existing.copy()
    end_idx = start_idx + len(new_data)
    updated[start_idx:end_idx] = new_data
    
    # 更新後のデータを保存
    np.save(filename, updated)
    print("配列の一部を更新しました")

# 使用例
original = np.arange(100)
np.save('updateable.npy', original)
update_array_section('updateable.npy', [999, 888, 777], 10)

3. 条件付きファイル保存

def conditional_save(data, filename, overwrite=False):
    """条件付きファイル保存"""
    if os.path.exists(filename) and not overwrite:
        print(f"ファイル {filename} は既に存在します")
        response = input("上書きしますか? (y/n): ")
        if response.lower() != 'y':
            return False
    
    np.save(filename, data)
    print(f"保存完了: {filename}")
    return True

# 使用例
new_data = np.random.randn(50, 50)
conditional_save(new_data, 'important.npy', overwrite=False)

ベストプラクティス

1. ファイル命名規則

# 分かりやすいファイル命名
def create_descriptive_filename(data_type, date, version=1):
    """説明的なファイル名を生成"""
    return f"{data_type}_{date}_v{version:02d}.npz"

# 使用例
filename = create_descriptive_filename('sales_data', '20241201', 3)
print(filename)  # sales_data_20241201_v03.npz

2. エラー処理の実装

def robust_save_load(data, filename, operation='save'):
    """堅牢な保存・読み込み処理"""
    try:
        if operation == 'save':
            np.save(filename, data)
            print(f"保存成功: {filename}")
            return True
        elif operation == 'load':
            loaded_data = np.load(filename)
            print(f"読み込み成功: {filename}")
            return loaded_data
    except Exception as e:
        print(f"{operation}エラー: {e}")
        return None

# 使用例
test_array = np.array([1, 2, 3])
robust_save_load(test_array, 'test.npy', 'save')
result = robust_save_load(None, 'test.npy', 'load')

まとめ

NumPy配列のバイナリファイル保存は、効率的なデータ管理の基本技術です。重要なポイント:

単一配列(.npy)

  • np.save()で保存、np.load()で読み込み
  • データ型と配列構造が完全に保持される
  • シンプルで高速な処理が可能

複数配列(.npz)

  • np.savez()またはnp.savez_compressed()で保存
  • 複数の配列を一つのファイルで管理
  • 圧縮による大幅なファイルサイズ削減

最適化のポイント

  • 大容量データには圧縮保存を推奨
  • メモリマップ機能で効率的な大容量ファイル処理
  • 適切なエラーハンドリングとファイル管理

これらの技術を活用することで、NumPy配列を効率的に保存・管理し、データ分析や機械学習のワークフローを大幅に改善できます。

■プロンプトだけでオリジナルアプリを開発・公開してみた!!

■AI時代の第一歩!「AI駆動開発コース」はじめました!

テックジム東京本校で先行開始。

■テックジム東京本校

「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。

<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。

<月1開催>放送作家による映像ディレクター養成講座

<オンライン無料>ゼロから始めるPython爆速講座

フリーランスボード

20万件以上の案件から、副業に最適なリモート・週3〜の案件を一括検索できるプラットフォーム。プロフィール登録でAIスカウトが自動的にマッチング案件を提案。市場統計や単価相場、エージェントの口コミも無料で閲覧可能なため、本業を続けながら効率的に高単価の副業案件を探せます。フリーランスボード

ITプロパートナーズ

週2〜3日から働ける柔軟な案件が業界トップクラスの豊富さを誇るフリーランスエージェント。エンド直契約のため高単価で、週3日稼働でも十分な報酬を得られます。リモートや時間フレキシブルな案件も多数。スタートアップ・ベンチャー中心で、トレンド技術を使った魅力的な案件が揃っています。専属エージェントが案件紹介から契約交渉までサポート。利用企業2,000社以上の実績。ITプロパートナーズ

Midworks 10,000件以上の案件を保有し、週3日〜・フルリモートなど柔軟な働き方に対応。高単価案件が豊富で、報酬保障制度(60%)や保険料負担(50%)など正社員並みの手厚い福利厚生が特徴。通勤交通費(月3万円)、スキルアップ費用(月1万円)の支給に加え、リロクラブ・freeeが無料利用可能。非公開案件80%以上、支払いサイト20日で安心して稼働できます。Midworks