1.PythonでExcelの巨大ファイルを扱う際に1000倍高速化する方法(2/2)まとめ
・joblibを使用するとファイルを並列で読み込み速度アップできる
・pickle形式でファイルを保存するとCSVより更に高速になる
・joblibでParallelにprefer=”threads”を指定すると更に高速化できる場合がある
2.pythonで複数ファイルを並列で読み込む方法
以下、www.kdnuggets.comより「Do You Read Excel Files with Python? There is a 1000x Faster Way」の意訳です。元記事は2021年9月、Nicolas Vandeputさんによる投稿です。
アイキャッチ画像のクレジットはPhoto by Hidde van Esch on Unsplash
アイデア#4:Joblibを使用してCSVインポートを並列化する
Pythonで10個のファイルをロードしたい時、各ファイルを1つずつロードするのではなく、すべてを一度に並行してロードしてみませんか?
joblibを使用してこれを簡単に行うことができます。
start = time.time() def loop(file_number): return pd.read_csv(f"Dummy {file_number}.csv") df = Parallel(n_jobs=-1, verbose=10)(delayed(loop)(file_number) for file_number in range(10)) df = pd.concat(df, ignore_index=True) end = time.time() print("CSV//:", end - start)
Joblibを使用してPythonでCSVファイルを並列にインポートします。
これは、シングルコアバージョンのほぼ2倍の速度です。ただし、原則として、8コアを使用してプロセスを8倍高速化できるとは期待しないでください。(ここでは、新しいM1チップを使用してMac Airで8コアを使用することで2倍の速度が得られました)。
(訳注:ライブラリのオーバーヘッドがプラスされるせいか無印 Colabで2.0秒でした。なお、ファイル読み込み処理は2分割され、それぞれ1.1秒と1.4秒で終わっています)
Joblibを使用したPythonでの単純な並列化
Joblibは、並列に関数を実行できるようにする単純なPythonライブラリです。実際には、joblibは、各反復処理が異なるスレッドによって実行されることを除いて、リスト内包のように機能します。
以下が例です。
def loop(file_number): return pd.read_csv(f"Dummy {file_number}.csv") df = Parallel(n_jobs=-1, verbose=10)(delayed(loop)(file_number) for file_number in range(10)) #equivalent to df = [loop(file_number) for file_number in range(10)]
joblibはスマートなリスト内包と考えてください。
アイデア#5:Pickleファイルを使用する
.csvファイルではなく、pickleファイル(Pythonで良く使用されるファイル保存形式)にデータを保存することで、(はるかに)高速に処理できます。
短所:Pickleファイルをエディターなどで開いて、その内容を直接確認/編集することはできません。
start = time.time() def loop(file_number): return pd.read_pickle(f"Dummy {file_number}.pickle") df = Parallel(n_jobs=-1, verbose=10)(delayed(loop)(file_number) for file_number in range(10)) df = pd.concat(df, ignore_index=True) end = time.time() print("Pickle//:", end - start)
実行時間を80%短縮しました!(訳注:無印 Colabで0.9024秒でした。)
一般に、Pickleファイルの操作はcsvファイルよりもはるかに高速です。ただし、その一方で、picklesファイルは通常、より多くのディスク容量を使用します。(今回の例だけではありません)
また実際には、Excel等の他システムからPickleファイル形式で直接データを保存することはできません。
以下の2つのケースでPickleを使用することをお勧めします。
(1)(Excelでこのファイルを開く予定がない場合に)Pythonのデータを保存して、後で/別のプロセスで使用したいと考えている時、データフレームを.csvではなくPickle形式で保存します
(2)同じファイルを複数回リロードする必要がある場合。
初めてファイルを開くときは、Pickleとして保存して、次回Pickleバージョンを直接ロードできるようにします。
例:トランザクションの月次データを使用するとします。(毎月、新しい月のデータをロードします)。すべての履歴データを.pickleとして保存できます。また、新しいファイルを受信するたびに、そのファイルを.csvとして一度ロードし、次回のために.pickleとして保持することができます。
ボーナス:Excelファイルを並行してロードする
Excelファイルを受け取ったとしましょう。その場合、それらをそのままロードする以外に選択肢はありません。 joblibを使用してこれを並列化することもできます。 上記のpickleコードと比較すると、ループ関数を更新するだけで済みます。
start = time.time() def loop(file_number): return pd.read_excel(f"Dummy {file_number}.xlsx") df = Parallel(n_jobs=-1, verbose=10)(delayed(loop)(file_number) for file_number in range(10)) df = pd.concat(df, ignore_index=True) end = time.time() print("Excel//:", end - start)
Pythonで並列化を使用してExcelファイルをロードする方法
読み込み時間を70%短縮できました(50秒から13秒に)。
(訳注:無印 Colabで45秒->38秒でした。)
このループを使用して、pickleファイルをその場で作成することもできます。そのため、次にこれらのファイルをロードするときに、非常に高速なロード時間を実現できます。
def loop(file_number): temp = pd.read_excel(f"Dummy {file_number}.xlsx") temp.to_pickle(f"Dummy {file_number}.pickle") return temp
要約
pickleファイルを並行してロードすることにより、ロード時間を50秒から10分の1秒未満に短縮しました。
Excel:50秒
CSV:0.63秒
よりスマートなCSV:0.62秒
並行で動かすCSV:0.34秒
並行で動かすpickle:0.07秒
並行で動かすExcel:13.5秒
更にボーナス#2:4倍高速な並列化
Joblibを使用すると、並列化バックエンドを変更して、いくつかのオーバーヘッドを取り除くことができます。 これを行うには、Parallelにprefer=”threads”を指定します。
def loop(file_number): return pd.read_pickle(f"Dummy {file_number}.pickle") df = Parallel(n_jobs=-1, verbose=0, prefer="threads")(delayed(loop)(file_number) for file_number in range(10)) df = pd.concat(df, ignore_index=True)
Preferred =”threads”を使用すると、プロセスをさらに高速に実行できます。
約0.0096秒の実行速度が得られます(2021 MacBook Airで50回以上実行)。CSVおよびExcel並列化でPreferred =”threads”を使用すると、次の結果が得られます。
Parallel | Parallel(Thread) | |
Excel | 16.54 | 51.07 |
CSV | 0.43 | 0.26 |
Pickles | 0.07 | 0.01 |
ご覧のとおり、「threads」バックエンドを使用すると、Excelファイルを読み取るときに逆に時間がかかるようになります。しかし、pickleを使用すると驚くべきパフォーマンスが得られます。(Excelファイルを1つずつロードするのには50秒かかりますが、並列でpickleファイルをスレッドで読み取るとわずか0.01秒です)。
LinkedInで私とつながりましょう!
略歴:Nicolas Vandeputは、需要予測と在庫最適化を専門とするサプライチェーンデータサイエンティストです。
3.PythonでExcelの巨大ファイルを扱う際に1000倍高速化する方法(2/2)関連リンク
1)www.kdnuggets.com
Do You Read Excel Files with Python? There is a 1000x Faster Way