K_DM Book
用語集
対象者 標準
対象者別の入口 →

対象者の設定はこのブラウザの中にだけ保存されます。

言語 JA

巨大なCSVでMemoryErrorになる

01.9.6

巨大なCSVでMemoryErrorになる

最終更新 2025-11-04 読了時間 3 分
まとめ
MemoryError: Unable to allocate 12.5 GiB for an array with shape (…) は、read_csv が CSV 全体を一度に DataFrame として展開しようとし、PC の空きメモリを超えた、という報告です。CSV は 1 文字 1 バイトですが、pandas は数値を 8 バイトの float64、文字列を Python オブジェクトとして保持するので、ディスク上 3 GB のファイルがメモリでは 10 GB を超えることがあります。対処は chunksize=100_000 で 10 万行ずつ読んで集計する、usecols で必要な 3 列だけ読む、dtype で int32・float32 に落とす、compression="gzip" で解凍せずに読む、の 4 つで、組み合わせるとメモリ使用量を元の 1/4 以下にできます。このページでは big.csv の amount 列の合計を出す例で、それぞれの効き方を示します。

直感 #

pd.read_csv("big.csv") は、ファイルを全行読み終えるまで結果を返さず、その間に全列・全行分の配列をメモリに確保します。数値列は 1 セル 8 バイト、文字列列は 1 セル 50 バイト以上を使うので、1 億セルの CSV は数 GB から十数 GB になります。MemoryError を避ける考え方は「一度に持つ量を減らす」ことで、行を分けて持つ(chunksize)、列を減らす(usecols)、1 セルのバイト数を減らす(dtype)、の 3 方向があり、どれも読み込みの引数 1 つで指定できます。

数 GB 以上の CSV を read_csv() で読み込むと、途中で

MemoryError: Unable to allocate XX GiB for an array with shape (…)

と表示されて処理が止まることがあります。メッセージの XX GiB が確保しようとした量、shape が行数と列数で、shape (100000000, 12) なら 1 億行 12 列を一度に持とうとしたことが分かります。ローカル PC の 16 GB では足りないため、分割して読む・不要な列を捨てる・型を最適化する といった工夫が必要です。


解決法 1: チャンク単位で読み込む #

chunksize=100_000 を付けると read_csv は DataFrame ではなくイテレータを返し、for で回すたびに 10 万行分の DataFrame が 1 つ渡されます。合計や件数のように「全行を同時に見なくてよい」集計なら、この 10 万行分のメモリだけで最後まで走れます。

1
2
3
4
5
6
7
8
import pandas as pd

chunks = pd.read_csv("big.csv", chunksize=100_000)
total = 0
for chunk in chunks:
    total += chunk["amount"].sum()

print(total)

解決法 2: 必要な列だけ読み込む #

分析に使う列が customer_id・amount・created_at の 3 列だけなら、usecols でその 3 列を指定します。12 列のファイルなら読み込み時点でメモリが 1/4 になります。

1
2
use_columns = ["customer_id", "amount", "created_at"]
df = pd.read_csv("big.csv", usecols=use_columns)

解決法 3: dtype を先に指定する #

pandas の型推定は安全側に寄っていて、整数は int64(8 バイト)、小数は float64(8 バイト)、文字列は object(50 バイト以上)になります。値の範囲が分かっている列は int32・float32・boolean を dtype で先に伝えると、1 セルあたりのバイト数が半分以下になります。

1
2
3
4
5
6
7
dtypes = {
    "customer_id": "int32",
    "amount": "float32",
    "is_active": "boolean",
}

df = pd.read_csv("big.csv", dtype=dtypes, memory_map=True)

解決法 4: 圧縮ファイルのまま読み込む #

gzip や zip で圧縮された CSV は、解凍して数 GB のファイルをディスクに置かなくても、compression を指定すればそのまま読めます。ネットワーク越しにダウンロードする場合も、圧縮ファイルのまま read_csv に渡すのが安全です。

1
df = pd.read_csv("big.csv.gz", compression="gzip")

使いどころと落とし穴 #

最初に確かめるのは、本当に全列を読む必要があるか(usecols)と、数値列・分類列の型を int32・float32・category に落としたか(dtype)の 2 点で、これだけで 12 列中 3 列・8 バイトから 4 バイトなら使用量は 1/8 になります。それでも入らないなら、合計や件数のように行をまたがない集計は chunksize=100_000 の分割処理に書き換え、中央値や結合のように全量が必要な処理は dask・polars・DuckDB のようにメモリに載せずに動くツールへ移します。読み込み後は df.memory_usage(deep=True).sum() / 1e9 で実際の GB 数を見て、見積もりとの差を確認してください。

参考 #

chunksize・usecols・dtype・compression の詳細は IO Tools (Text, CSV) — pandas documentation に、同じ API でチャンクを並列処理する方法は Dask DataFrame Documentation にあります。