pandas でカテゴリデータを扱うとき、文字列のまま保持するとメモリを大量に消費します。category 型を使えば、メモリ使用量を大幅に削減できます。
文字列とカテゴリ型のメモリ比較
まず、どれくらい違うか確認してみましょう。
import pandas as pd import numpy as np # 100万行のデータを作成 n = 1_000_000 df = pd.DataFrame({ 'status': np.random.choice(['active', 'inactive', 'pending'], n) }) # 文字列型のメモリ使用量 print(f"object型: {df['status'].memory_usage(deep=True) / 1024 / 1024:.2f} MB") # カテゴリ型に変換 df['status'] = df['status'].astype('category') print(f"category型: {df['status'].memory_usage(deep=True) / 1024 / 1024:.2f} MB")
結果は環境によりますが、文字列型で約 60MB だったものが、カテゴリ型では 1MB 以下になることもあります。値の種類が少ないほど効果が大きくなります。
カテゴリ型の仕組み
カテゴリ型は、内部的に整数コードとカテゴリ名のマッピングを持っています。
元データ: ['active', 'inactive', 'active', 'pending']
カテゴリ: {0: 'active', 1: 'inactive', 2: 'pending'}
整数コード: [0, 1, 0, 2]
文字列を繰り返し保持する代わりに、短い整数コードだけを保持するため、メモリ効率がよくなります。
カテゴリ型への変換方法
既存のデータをカテゴリ型に変換するには astype('category') を使います。
df['status'] = df['status'].astype('category')
データ読み込み時に指定することもできます。
df = pd.read_csv('data.csv', dtype={'status': 'category'})
カテゴリの確認と操作
カテゴリの一覧は .cat.categories で確認できます。
print(df['status'].cat.categories)
カテゴリを追加したり、順序を変えたりもできます。
# カテゴリを追加 df['status'] = df['status'].cat.add_categories(['deleted']) # 使われていないカテゴリを削除 df['status'] = df['status'].cat.remove_unused_categories() # カテゴリの順序を変更 df['status'] = df['status'].cat.reorder_categories(['pending', 'active', 'inactive'])
順序付きカテゴリ
カテゴリに順序を持たせることもできます。これにより、比較演算が可能になります。
df['size'] = pd.Categorical( ['S', 'M', 'L', 'S', 'XL'], categories=['S', 'M', 'L', 'XL'], ordered=True ) # 比較演算が可能 print(df[df['size'] > 'M'])
カテゴリ型が効果的なケース
効果が大きい
値の種類が少なく、同じ値が繰り返し出現するデータ。例:国名、ステータス、曜日など。
効果が小さい
値の種類が多い、またはほぼユニークなデータ。例:ID、名前、自由記述など。
注意点
カテゴリ型は便利ですが、いくつか注意点があります。
カテゴリにない値を代入しようとするとエラーになります
文字列メソッド(str アクセサ)は一部制限があります
他のデータフレームと結合するとき、カテゴリが異なると問題が起きることがあります
大規模データを扱うときは、読み込み時にカテゴリ型を指定しておくとメモリを節約でき、処理速度も向上します。特にグループ化やソートの操作が速くなります。