Pandas で Parquet / Feather ファイルを読み取る

Parquet と Feather は、ビッグデータ分析と高速読み書きのシナリオ向けに設計された、2 つの効率的な列指向データストレージ形式です。CSV と比較して、圧縮率とクエリパフォーマンスに優れています。


Parquet と Feather を使う理由

列指向ストレージ形式の主な利点:

特性 CSV Parquet Feather
ストレージ形式 行指向 列指向 列指向
読み取り速度 慢 速い 非常に速い
書き込み速度 中 快 非常に速い
圧縮率 低 高 中
クロス言語サポート 汎用 Java/Python/R Python/R

Parquet は Apache 財団のプロジェクトであり、ビッグデータエコシステム(Hadoop、Spark、DuckDB など)で広く使用されています。Feather は Arrow プロジェクトのネイティブ実装であり、極限の読み書き速度に重点を置いています。


Parquet ファイル操作

依存関係のインストール

pip install pyarrow fastparquet

PyArrow と FastParquet はどちらも Parquet の Python 実装です。PyArrow がデフォルトのオプションで、FastParquet は一部のシナリオではより高速です。

Parquet ファイルを読み取る

例

import pandas as pd

# Parquet ファイルを読み取る(デフォルトは pyarrow を使用)
df = pd.read_parquet("data.parquet")

# 特定のエンジンを指定して使用
df = pd.read_parquet("data.parquet", engine="pyarrow")
df = pd.read_parquet("data.parquet", engine="fastparquet")

# リモートの Parquet ファイルを読み取る
df = pd.read_parquet("s3://bucket/data.parquet")

# ファイルの特定の列を読み取る(列の絞り込み、パフォーマンス向上)
df = pd.read_parquet("data.parquet", columns=["name", "age", "city"])
print(df.head())

Parquet ファイルを書き込む

例

import pandas as pd

# テストデータを準備
df = pd.DataFrame({
    "id": range(1, 10001),
    "name": ["ユーザー" + str(i) for i in range(1, 10001)],
    "age": [20, 25, 30, 35] * 2500,
    "city": ["北京", "上海", "広州", "深セン"] * 2500,
    "score": [round(i * 0.1, 2) for i in range(1, 10001)]
})

# Parquet ファイルを書き込む(デフォルトは pyarrow エンジンを使用)
df.to_parquet("data.parquet", index=False)

# 圧縮方式を指定(snappy は速度が速く、gzip は圧縮率が高い)
df.to_parquet("data_snappy.parquet", compression="snappy", index=False)
df.to_parquet("data_gzip.parquet", compression="gzip", index=False)
df.to_parquet("data_none.parquet", compression=None, index=False)  # 圧縮なし

# ファイルサイズを確認
import os
print("ファイルサイズ比較:")
print(f"元の CSV 推定: {len(df) * 50 / 1024 / 1024:.2f} MB")
print(f"snappy 圧縮: {os.path.getsize('data_snappy.parquet') / 1024 / 1024:.2f} MB")
print(f"gzip 圧縮: {os.path.getsize('data_gzip.parquet') / 1024 / 1024:.2f} MB")
print(f"圧縮なし: {os.path.getsize('data_none.parquet') / 1024 / 1024:.2f} MB")

高速 Parquet エンジンを使用する

例

import pandas as pd
import time

# 異なるエンジンの書き込みパフォーマンスをテスト
df = pd.DataFrame({
    "id": range(1, 100001),
    "value": range(1, 100001)
})

# pyarrow エンジンで書き込み
start = time.time()
df.to_parquet("test_pyarrow.parquet", engine="pyarrow", compression="snappy")
print(f"pyarrow 書き込み時間: {time.time() - start:.3f}s")

# fastparquet エンジンで書き込み
start = time.time()
df.to_parquet("test_fastparquet.parquet", engine="fastparquet", compression="snappy")
print(f"fastparquet 書き込み時間: {time.time() - start:.3f}s")

Feather ファイル操作

Feather は Arrow プロジェクトの Python 実装であり、極限のメモリ読み書き速度に重点を置いています。

依存関係のインストール

pip install pyarrow

Feather ファイルを読み取る

例

import pandas as pd

# Feather ファイルを読み取る
df = pd.read_feather("data.feather")

# v2 バージョンの Feather ファイルを読み取る(より汎用的)
df = pd.read_feather("data.feather", version="2.0")

# 特定の列を読み取る
df = pd.read_feather("data.feather", columns=["name", "age"])
print(df.head())

Feather ファイルを書き込む

例

import pandas as pd

# テストデータを準備
df = pd.DataFrame({
    "id": range(1, 10001),
    "name": ["ユーザー" + str(i) for i in range(1, 10001)],
    "value": [round(i * 0.1, 2) for i in range(1, 10001)]
})

# Feather ファイルを書き込む
df.to_feather("data.feather")

# LZ4 圧縮(より高速)
df.to_feather("data_lz4.feather", compression="lz4")

# ZSTD 圧縮(より高い圧縮率)
df.to_feather("data_zstd.feather", compression="zstd")

# ファイルサイズを確認
import os
print(f"圧縮なし: {os.path.getsize('data.feather') / 1024:.2f} KB")
print(f"LZ4: {os.path.getsize('data_lz4.feather') / 1024:.2f} KB")
print(f"ZSTD: {os.path.getsize('data_zstd.feather') / 1024:.2f} KB")

パフォーマンス比較テスト

例

import pandas as pd
import numpy as np
import time
import os
import tempfile

# テストデータを作成
np.random.seed(42)
n_rows = 1000000
df = pd.DataFrame({
    "id": range(n_rows),
    "category": np.random.choice(["A", "B", "C", "D"], n_rows),
    "value": np.random.randn(n_rows),
    "flag": np.random.choice([True, False], n_rows),
    "date": pd.date_range("2020-01-01", periods=n_rows, freq="1min")
})

# 一時ディレクトリを作成
with tempfile.TemporaryDirectory() as tmpdir:
    # CSV 書き込み
    start = time.time()
    df.to_csv(f"{tmpdir}/data.csv", index=False)
    csv_write = time.time() - start

    start = time.time()
    df_csv = pd.read_csv(f"{tmpdir}/data.csv")
    csv_read = time.time() - start

    # Parquet 書き込み
    start = time.time()
    df.to_parquet(f"{tmpdir}/data.parquet", index=False)
    pq_write = time.time() - start

    start = time.time()
    df_pq = pd.read_parquet(f"{tmpdir}/data.parquet")
    pq_read = time.time() - start

    # Feather 書き込み
    start = time.time()
    df.to_feather(f"{tmpdir}/data.feather")
    feather_write = time.time() - start

    start = time.time()
    df_feather = pd.read_feather(f"{tmpdir}/data.feather")
    feather_read = time.time() - start

    # 結果を出力
    print(f"{'形式':<10} {'書き込み時間':<12} {'読み取り時間':<12} {'ファイルサイズ':<12}")
    print("-" * 50)
    print(f"{'CSV':<10} {csv_write:.3f}s{'':<5} {csv_read:.3f}s{'':<5} {os.path.getsize(f'{tmpdir}/data.csv')/1024/1024:.2f}MB")
    print(f"{'Parquet':<10} {pq_write:.3f}s{'':<5} {pq_read:.3f}s{'':<5} {os.path.getsize(f'{tmpdir}/data.parquet')/1024/1024:.2f}MB")
    print(f"{'Feather':<10} {feather_write:.3f}s{'':<5} {feather_read:.3f}s{'':<5} {os.path.getsize(f'{tmpdir}/data.feather')/1024/1024:.2f}MB")

使用シーンと選択のアドバイス

シーン 推奨形式 理由
ビッグデータ分析 Parquet 圧縮率が高い、列指向クエリが速い、エコシステムが広い
Python/R データ受け渡し Feather 読み書きが非常に速い、Arrow ネイティブサポート
Spark/Hadoop 統合 Parquet ビッグデータエコシステムの標準形式
データバックアップ/アーカイブ Parquet 圧縮率が高い、スキーマ進化をサポート
一時データキャッシュ Feather 読み書きが最速

よくある質問

1、Parquet 読み取りエラー

pyarrow または fastparquet がインストールされていることを確認してください:pip install pyarrow

2、ファイル破損

書き込み時にデータが完全にディスクに書き込まれるようにし、書き込み後にファイルの読み取り可能性を検証することをお勧めします。

3、バージョン互換性

Parquet の異なるバージョンでは互換性の問題が発生する可能性があるため、プロジェクトで固定バージョンを使用することをお勧めします。

その他の拡張