PandasのDataFrameのメモリ使用量を削減する方法

2020年5月6日水曜日

AI Python

t f B! P L

Pythonで特徴量を作るうえで重要なPandasのDataFrameですが、
何千万行もあるような大きなデータを扱うとメモリエラーが出ますよね!
そんな方に朗報です!下のコードをコピペして
使うだけで簡単にメモリ使用量を減らすことができます。

# 必要なライブラリをインポート
import pandas as pd
import numpy as np
import gc

# メモリ使用量を削減する関数(これをコピペして使いまわせばOK)
def reduce_mem_usage(df, verbose=True):
    numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
    start_mem = df.memory_usage().sum() / 1024**2    
    for col in df.columns:
        col_type = df[col].dtypes
        if col_type in numerics:
            c_min = df[col].min()
            c_max = df[col].max()
            if str(col_type)[:3] == 'int':
                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
                    df[col] = df[col].astype(np.int8)
                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
                    df[col] = df[col].astype(np.int16)
                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
                    df[col] = df[col].astype(np.int32)
                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
                    df[col] = df[col].astype(np.int64)  
            else:
                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
                    df[col] = df[col].astype(np.float16)
                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
                    df[col] = df[col].astype(np.float32)
                else:
                    df[col] = df[col].astype(np.float64)    
    end_mem = df.memory_usage().sum() / 1024**2
    if verbose: print('Mem. usage decreased to {:5.2f} Mb ({:.1f}% reduction)'.format(end_mem, 100 * (start_mem - end_mem) / start_mem))
    return df

# DataFrameを上記関数に入れる(このように使うだけ!)
df = pd.read_csv("hogehoge.csv")
df = reduce_mem_usage(df)

めっちゃ簡単ですよね!
データ解析コンペプラットフォームのkaggleで非常によく使われています。
これ、何やってるかと言うと数値型を必要最低限の型に変換です。
例えばyearというカラムがあって1900~2020が入ってるとします。
pd.read_csvでそのまま読み込むと整数はint64になります。
整数型で扱える範囲は下表の通りです。
dtype説明
int8整数(-128~127)
int16整数(-32768~32767)
int32整数(-2147483648~2147483647)
int64整数(-9223372036854775808~ 9223372036854775807)
西暦のyearならint16で十分ですね!
これ、int64だと1行で64bit(8byte)メモリを使うという意味なので
int16に変換するだけでメモリを4分の1の16bitに減らせるんですね。
先ほどのreduce_mem_usage関数は、DataFrameの中で
整数型と浮動小数点型のカラムを見て最大値や最小値から
メモリを一番減らせる型に変換するようになってます。
情報量が減る心配もありませんので是非使ってみてください。

このブログを検索

ブログ アーカイブ

AD

自己紹介

自分の写真
機械学習による売上予測モデル構築や商品ポートフォリオ最適化に取り組むAI屋です。E資格・G検定保有。LINEスタンプ販売やYoutubeもやってます。

QooQ