目的
巨大なFXのヒストリカルデータや、TickデータのCSV(GBサイズ)を高速分析するために、バイナリのparquet化。その後Numpyやbinファイルを作って解析する
サンプルデータ
※今回ヘッダなしのTickデータを使用。
カラム構造:time-stamp ,bid,ask,何のデータか不明のカラム
20251201 000000079,155.548000,155.551000,0
20251201 000000186,155.552000,155.554000,0
20251201 000000291,155.551000,155.554000,0
20251201 000000449,155.549000,155.552000,0
20251201 000000605,155.549000,155.552000,0
20251201 000000709,155.548000,155.552000,0
—中略—-
※:CSVサイズ:1.5GB 34,045,106行
記事に記載のコードは上記構造のデータを基準に作成しています。カラムの付与については自身のデータのカラムに読み替えてください。
Pandasを使わない理由
- メモリ不足(OOM)の回避: PandasはCSVの全データを一度にメモリ上に展開するため、1.4GB(約3,200万行)規模のティックデータではPCがフリーズまたはクラッシュするリスクが高い。
- Polars/PyArrowの圧倒的優位性: ストリーミング処理やC++ベースの高速エンジンを使用することで、メモリをほとんど消費せずに数億行スケールのデータを一瞬でParquet化できる。
- スキーマ(ヘッダ)の重要性: Parquetにする時点で列名を確定させておくことで、後のNumPy解析時に必要な列だけをピンポイントで超高速にロード可能になる。
polars使用で作成
ヘッダなしの場合(ヘッダを付与)
元データにヘッダがないCSVに、列名(スキーマ)を指定・付与しながらParquetへ変換する(NumPy解析用の空フラグ列も事前に追加)。
import polars as pl #付与するカラム名の定義
column_names = ["timestamp", "bid", "ask", "status_code"]
# 遅延評価(Lazy)とストリーミングで省メモリ・高速処理
df = pl.scan_csv(
"input_no_header.csv",
has_header=False,
new_columns=column_names,
).with_columns(
pl.lit(0).alias("tick_flag") # NumPy解析用のフラグ列(初期値0)を先に追加
)
#Parquetファイルへ直接書き出しdf.sink_parquet("output_polars_no_header.parquet")
ヘッダがある場合
元データにすでにヘッダが存在するCSVから変換する。
import polars as plhas_header=True #でそのまま読み込み、フラグ列を追加して保存
df = pl.scan_csv(
"input_with_header.csv",
has_header=True,
).with_columns(
pl.lit(0).alias("tick_flag")
)df.sink_parquet("output_polars_with_header.parquet")
pyarrow使用で作成
ヘッダなしの場合(ヘッダを付与)
C++ベースの高速シリアライザを使用し、列名を設定してParquetに書き出す。
import pyarrow.csv as pv
import pyarrow.parquet as pq
import pyarrow as pacolumn_names = ["timestamp", "bid", "ask", "status_code"]
#読み込み時にカラム名を設定
options = pv.ReadOptions(column_names=column_names)
table = pv.read_csv("input_no_header.csv", read_options=options)
#Tickフラグ用の列(初期値0)を追加して保存
tick_flag_array = pa.array([0] * len(table), type=pa.int32())
table = table.append_column("tick_flag", tick_flag_array)pq.write_table(table, "output_pyarrow_no_header.parquet")
ヘッダがある場合
1行目のヘッダを自動認識させてParquetに変換する。
import pyarrow.csv as pv
import pyarrow.parquet as pq
import pyarrow as pa #ヘッダを自動認識してロード
table = pv.read_csv("input_with_header.csv")
#フラグ用の列を追加して保存
tick_flag_array = pa.array([0] * len(table), type=pa.int32())
table = table.append_column("tick_flag", tick_flag_array)pq.write_table(table, "output_pyarrow_with_header.parquet")
結果:もとのCSV1.5GBから214.2MBまでサイズダウン。

