「Pandas使うよりPolarsの方がいいよ」は本当かもね??
こんにちは☀️
TRUSTART株式会社のみつです!
最近は、大きめなデータを扱うことが多いです。
そんな中、先輩エンジニアにpandasよりもPolarsの方がいいという話を聞き、Polarsを使うようになったんですが、「本当に??」という気持ちもどこかにありました。(自分の知らないもの恐怖症)
実際に使ってみるとすごく早い気がして、いいじゃん!や使う中での学びもあり、少しまとめてみた記事になります。
😕扱うデータが重すぎる
扱っているデータは、本当に大きくPC壊れちゃうんじゃないかと思うぐらいです。
数十万件〜数百万件のデータは、普通にある。
数千万件のデータだって、至る所に。
ほんの少し実行スピードが違うだけで、実行完了までに大きな差が出てきます。
😕とあるCSVデータを縦にマージしたい
私個人が使っているコードの一部を紹介しつつ、Polarsでの実装を眺めてみます。
下記では、input
ディレクトリにある output_
というプレフィックスから始まるcsvを縦に合体します。
input
ディレクトリなのに、output_
は、紛らわしいですね・・・。💦
どこかでoutputされたものたちをinputディレクトリに全部入れてさらに合体したい、という実装です。
📍Polarsで実装をするとこうなる
import os
import polars as pl
import time
INPUT_DIR: str = "./input"
INPUT_FILE_PREFIX: str = "output_"
INPUT_FILE_SCHEMA: dict[str, pl.DataType] = {
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
"XXX": pl.Utf8,
}
def get_file_paths() -> list[str]:
"""
入力ディレクトリ内のファイルパスを取得する関数
"""
file_paths = []
for file_name in os.listdir(INPUT_DIR):
if file_name.startswith(INPUT_FILE_PREFIX):
file_paths.append(os.path.join(INPUT_DIR, file_name))
return file_paths
def get_input_csvs(file_paths: str) -> list[pl.DataFrame]:
"""
入力CSVファイルを読み込み、整形して返す関数
"""
dataframes = pl.DataFrame()
for file_path in file_paths:
df = pl.read_csv(
file_path, schema=INPUT_FILE_SCHEMA, infer_schema_length=10000000000
)
dataframes = pl.concat([dataframes, df])
return dataframes
def fix_no_rows(df: pl.DataFrame) -> pl.DataFrame:
"""
'No'列の値を1から始まる連番に修正する関数
"""
df = df.with_columns((pl.arange(1, df.height + 1)).alias("No"))
return df
def main():
start_time = time.time()
file_paths = get_file_paths()
dataframes = get_input_csvs(file_paths)
dataframes = fix_no_rows(dataframes)
dataframes.write_csv("../output_XXX/merged_output.csv")
end_time = time.time()
elapsed_time = end_time - start_time
print(f"Processing completed in {elapsed_time:.2f} seconds.")
if __name__ == "__main__":
main()
print("Processing completed.")
📍pandasで実装をするとこうなる
Polarsとあまり変わらない実装にはなりました。
import os
import pandas as pd
import time
INPUT_DIR = "./input"
INPUT_FILE_PREFIX = "output_"
INPUT_FILE_SCHEMA = {
"XXX": str,
"XXX": str,
"XXX": str,
"XXX": str,
"XXX": str,
"XXX": str,
"XXX": str,
"XXX": str,
"XXX": str,
"XXX": str,
"XXX": str,
"XXX": str,
"XXX": str,
"XXX": str,
"XXX": str,
"XXX": str,
"XXX": str,
}
def get_file_paths() -> list[str]:
"""
入力ディレクトリ内のファイルパスを取得する関数
"""
file_paths = []
for file_name in os.listdir(INPUT_DIR):
if file_name.startswith(INPUT_FILE_PREFIX):
file_paths.append(os.path.join(INPUT_DIR, file_name))
return file_paths
def get_input_csvs(file_paths: list[str]) -> pd.DataFrame:
"""
入力CSVファイルを読み込み、整形して返す関数
"""
dataframes = []
for file_path in file_paths:
df = pd.read_csv(file_path, dtype=INPUT_FILE_SCHEMA, encoding="utf-8")
dataframes.append(df)
merged = pd.concat(dataframes, ignore_index=True)
return merged
def fix_no_rows(df: pd.DataFrame) -> pd.DataFrame:
"""
'No'列の値を1から始まる連番に修正する関数
"""
df["No"] = [str(i) for i in range(1, len(df) + 1)]
return df
def main():
start_time = time.time()
file_paths = get_file_paths()
dataframes = get_input_csvs(file_paths)
dataframes = fix_no_rows(dataframes)
dataframes.to_csv("../output_XXX/merged_output.csv", index=False, encoding="utf-8")
end_time = time.time() # 計測終了
elapsed_time = end_time - start_time
print(f"Processing completed in {elapsed_time:.2f} seconds.")
if __name__ == "__main__":
main()
print("Processing completed.")
📍実行結果の比較
計測は end_time - start_time
という雑なtimeを使った引き算です・・・。💦
時間計測でいい方法が他にもあるのかは調べてません!!
比較の仕方はさておき、スピードが全然違うじゃん、という結果。
20万行程度のcsvを3つ縦に結合するだけだったんですが、明らかに実行スピードが異なります。
⭐️Polars
python polars_main.py
Processing completed in 0.18 seconds.
Processing completed.
⭐️pandas
python pandas_main.py
Processing completed in 1.63 seconds.
Processing completed.
やっぱりPolarsなのかなぁ
やっぱりPolarsがいいのかなという気持ちになっているの今。
Polarsのドキュメントを読んでたらなるほどな一文を発見。
そもそもpandasは、シングルスレッドで動くけど、Polarsはマルチスレッドで動くようにいい感じになっているということ。
早い理由に納得感ありです。
Pandasは、Pythonデータ分析において広く採用されている包括的なツールであり、豊富な機能セットと強力なコミュニティサポートで知られています。しかし、シングルスレッドであるため、中規模および大規模データセットではパフォーマンスとメモリ使用量に問題が生じることがあります。
一方、Polarsは単一ノード上での高性能マルチスレッドコンピューティングに最適化されており、特に中規模から大規模のデータ処理において、速度とメモリ効率を大幅に向上させます。より構成可能で厳密なAPIにより、表現力が向上し、スキーマ関連のバグが減少します。
🔥まとめ
🔥Polars良さそう。笑🔥
あとこういう時は、pandasを使うんだを知りたい。
もっと色々調べてみようと思います。
おわり。
参考
最後に
TRUSTART株式会社は、一緒に働くメンバーを募集しています!
インターンメンバーも大募集中です!
興味を持っていただいた方は、ぜひ弊社のページをご確認ください!!!

「人とデータで全てを可能にする」 不動産領域に関連する、あらゆるビジネスのDX化にチャレンジし、「テクノロジー×人」の力で社会課題を解決するTRUSTART株式会社のテックブログです! 採用情報はこちら:trustart.co.jp/recruit/
Discussion