Pythonで大量のデータを扱っていると、Parquet(パーケ) というファイル形式を目にすることがあります。
CSVはよく知っているけれど、Parquetは何が違うのか。「列指向」という言葉を聞いたことはあるけれど、いまひとつイメージできない。そんな人も多いのではないでしょうか。
今回は、レース車両のテレメトリデータを例に、Parquetの基本的な仕組みを紹介します。Pythonを使ってファイルを作り、GT7の実測データで容量や読み込み時間の違いも確かめてみます。
1. Parquetって何?
Parquetは、データを効率よく保存・読み込みするためのファイル形式です。
CSVと同じように、表形式のデータを保存できます。ただし、CSVとはデータの保存方法が大きく異なります。
例えば、レース車両から取得したテレメトリデータを考えてみましょう。
| Time (s) | Speed (km/h) | Throttle (%) | Brake (%) |
|---|---|---|---|
| 0.0 | 100 | 50 | 0 |
| 0.1 | 105 | 60 | 0 |
| 0.2 | 110 | 70 | 0 |
| 0.3 | 108 | 0 | 30 |
車速、アクセル開度、ブレーキ開度などが時刻ごとに記録されています。
実際のレースデータでは、これらに加えてエンジン回転数、各種温度、サスペンション変位など、数百から数千のチャンネルを扱うこともあります。
こうした大量のデータを効率よく扱うために役立つのがParquetです。
2. 列指向ってどういう意味?
Parquetの特徴を理解するうえで重要なのが、列指向(Column-oriented) という考え方です。
通常、CSVではデータが行単位で記録されています。
例えば、先ほどのテレメトリデータなら、ファイルには次のように記録されます。
Time,Speed,Throttle,Brake
0.0,100,50,0
0.1,105,60,0
0.2,110,70,0
0.3,108,0,30
時刻、車速、アクセル開度、ブレーキ開度という順番で、1行ずつデータが並んでいます。
一方、Parquetは同じ列のデータをまとめて保存する「列指向」のファイル形式です。
考え方を単純化すると、次のようなイメージです。
Time : 0.0, 0.1, 0.2, 0.3
Speed : 100, 105, 110, 108
Throttle : 50, 60, 70, 0
Brake : 0, 0, 0, 30
つまり、CSVは行ごと、Parquetは列ごとにデータをまとめるという違いがあります。
実際のParquetは、データを行グループに分割したうえで列ごとに保存するなど、もう少し複雑な構造を持っていますが、まずはこのイメージで十分です。
3. なぜ列指向がレースデータ分析に向いているの?
例えば、説明用に500チャンネルのテレメトリデータがあるとします。後半のGT7実験では、実際に記録した82列のデータを使います。
その中から車速とアクセル開度だけを取り出して、グラフに表示したい場合を考えてみましょう。
CSVでは、一般的な読み込み方法だと、使わないチャンネルも含めてデータを処理することになります。
一方、Parquetは列ごとにデータがまとめられているため、必要なチャンネルだけを効率よく読み込めます。
500チャンネルすべてを読み込む必要がないので、読み込むデータ量を大幅に減らせる可能性があります。
レースデータ分析では、毎回すべてのチャンネルを使用するとは限りません。車速だけ、ブレーキだけ、あるいは複数のサスペンション変位だけを比較するといったケースも多くあります。
こうした使い方と列指向は相性がよいのです。
ただし、Parquetが必ずCSVより高速というわけではありません。データの規模や読み込み方法、分析内容によって効果は変わります。
4. ファイルサイズも小さくなりやすい
Parquetには、データを効率よく圧縮できるというメリットもあります。
例えば、ブレーキ開度のデータを考えてみましょう。
0, 0, 0, 0, 0, 0, 0, 0, 30, 50, 80
ブレーキを踏んでいない区間では、0という値が続いています。
このように同じ種類のデータがまとまっていると、値の繰り返しなどの特徴を利用して効率よく保存しやすくなります。
Parquetでは、こうしたデータの特徴に応じたエンコーディングや圧縮方式を利用できます。
その結果、CSVよりファイルサイズが小さくなるケースが多くあります。
データ容量が減れば、ファイルの保存に必要なストレージ容量や、ネットワーク経由で読み込むデータ量も削減できる可能性があります。
5. Parquetファイルはどうやって作るの?
ここまで仕組みを説明してきましたが、実際にParquetファイルを作るのはそれほど難しくありません。
Pythonを使えば、CSVファイルを簡単にParquet形式へ変換できます。
まず、必要なライブラリをインストールします。
pip install pandas pyarrow
次に、PythonでCSVファイルを読み込み、Parquet形式で保存します。
import pandas as pd
df = pd.read_csv("telemetry.csv")
df.to_parquet("telemetry.parquet", index=False)
これだけです。
telemetry.csv というファイルから、telemetry.parquet が作成されます。
今回は、pandasを通じてPyArrowを使っています。列指向への変換や圧縮などの内部処理はPyArrowが担当するため、自分で複雑な変換処理を実装する必要はありません。
もちろん、CSVを経由せずにPythonで作成したデータを直接Parquet形式で保存することもできます。
6. Parquetファイルを読み込んでみよう
作成したParquetファイルは、Pythonで簡単に読み込めます。
import pandas as pd
df = pd.read_parquet("telemetry.parquet")
print(df.head())
さらに、Parquetの特徴を活かして、必要なチャンネルだけを読み込んでみましょう。
df = pd.read_parquet(
"telemetry.parquet",
columns=["Time", "Speed", "Throttle"]
)
columns に必要な列名を指定することで、Time、Speed、Throttleの3列だけを読み込めます。
大量のチャンネルを持つテレメトリデータでは、このような読み込み方が役立ちます。
7. GT7の実測データで比べてみる
ここまで、Parquetの仕組みとPythonでの使い方を紹介しました。では、実際の走行データでは、どのくらい違いが出るのでしょうか。
GT7で記録した走行ログを使って、ファイルサイズと読み込み時間を比較してみました。
比較に使ったデータ
11コース・10車種にわたる異なる29ファイルを結合し、205,002行のデータを用意しました。同じログを繰り返して増やしたものではありません。
計測データは82列です。元ファイルを識別するためのIDを1列加え、CSVとParquetのどちらにも同じ83列を保存しました。欠損値はなく、読み込み後の型と値が一致することも確認しています。
比較用のCSVは、元のログから型とIDをそろえて保存し直したものです。ファイルごとの時刻はそのまま残し、無理に連続した時間軸にはしていません。
容量と読み込み時間はどう変わった?
同じデータをCSVと、Snappy・ZSTDで圧縮したParquetに保存しました。SnappyとZSTDは、どちらも圧縮方式の名前です。
CSV → Parquet(Snappy)の実測結果
- ファイル容量
- 約59%削減
- 全83列の読み込み速度
- 約8.5倍
- 主要3列の読み込み速度
- 約40.4倍
GT7実測205,002行・83列でのCSV比です。読み込み速度は各15回の中央値から算出しています。今回の測定条件での結果であり、効果はデータや実行環境によって変わります。
| 形式 | 容量 (MiB) | 全83列 (ms) | 主要3列 (ms) |
|---|---|---|---|
| CSV | 95.0 | 3,084.1 | 993.6 |
| Parquet・Snappy | 39.2 | 363.6 | 24.6 |
| Parquet・ZSTD | 30.7 | 424.1 | 27.5 |
読み込み時間は、各条件を15回測定した中央値です。1,000msが1秒、1MiBは1,048,576バイトです。
主要3列は、時刻のtime_of_day_ms、車速のspeed_kmh、アクセル開度のthrottle_pctです。CSVにもusecols、Parquetにもcolumnsを指定して、同じ3列を読み込んでいます。時刻はゲーム内のミリ秒カウンターで、前半の説明用データのTimeとは名前や単位が異なります。
容量は、Snappyで約59%、ZSTDで約68%小さくなりました。一方、今回の全83列と主要3列の読み込み時間はSnappyのほうが短く、最も小さく保存できる形式が、最も速く読めるとは限りませんでした。
読み込む列数を変えると?
さらに、読み込む列数を3・10・25・50・83列と変えて比較しました。最初に時刻・車速・アクセルを選び、ブレーキやエンジン回転数などを順に加える形で、測定前に列の組み合わせを固定しています。
今回の測定では、CSVもParquetも、列を少なくすると処理時間が短くなりました。
全83列から3列へ絞ると、CSVは約3,084msから約994msに、Snappyは約364msから約25ms、ZSTDは約424msから約28msになっています。必要なチャンネルだけを繰り返し分析する使い方に、Parquetが向いていることを実感しやすい結果です。
測定条件と注意点
CSVは通常のpd.read_csv()、ParquetはPyArrowを使った単一スレッドで読み込みました。同じPCのローカルストレージで、各条件2回のウォームアップ後に測定し、実行順序は毎回変えています。CSVからParquetへの変換時間は、読み込み時間に含めていません。
Windowsを再起動し、不要なアプリを終了してから測定しました。ただし、OSのファイルキャッシュや背景で動く処理は制御しておらず、空きメモリが少ない環境での実験です。数値は今回のデータと環境での結果として見てください。
また、形式による差には圧縮や数値変換なども含まれます。すべてを列指向だけの効果とは言い切れませんし、別のデータでも同じ速度や圧縮率になるとは限りません。
列数別の詳しい測定結果を見る
| 読み込み列数 | CSV 中央値 (ms) | Snappy 中央値 (ms) | ZSTD 中央値 (ms) |
|---|---|---|---|
| 3 | 993.59 | 24.57 | 27.53 |
| 10 | 1,186.27 | 44.84 | 54.81 |
| 25 | 1,794.23 | 155.11 | 165.14 |
| 50 | 2,048.47 | 244.66 | 265.11 |
| 83 | 3,084.14 | 363.55 | 424.08 |
GT7の実測データ(205,002行・83列)を使い、CSVとParquet(Snappy・ZSTD)の読み込み時間を比較しました。いずれも指定した列だけを読み込み、各条件15回の測定中央値を掲載しています。
結果は今回の測定条件での値であり、データや実行環境によって変わります。
8. CSVとParquet、どちらを使えばいい?
ここまでParquetのメリットを紹介してきましたが、CSVが不要になるわけではありません。
| 比較項目 | CSV | Parquet |
|---|---|---|
| データ形式 | テキスト | バイナリ |
| 中身の確認 | テキストエディタでも可能 | 対応ツールが必要 |
| 必要な列だけの読み込み | 方法による | 得意 |
| ファイルサイズ | 大きくなりやすい | 小さくなりやすい |
| 主な用途 | データ交換・簡単な確認 | 大量データの保存・分析 |
例えば、少量のデータをExcelで確認したり、ほかの人に渡したりするならCSVは便利です。
一方、大量のテレメトリデータを保存し、繰り返し分析する用途ならParquetが有力な選択肢になります。
今回のGT7ログでも、保存容量を減らし、必要な列だけを短時間で読み込めました。例えば、記録・受け渡しにはCSVを使い、繰り返し分析するデータはParquetにも変換しておく、という使い分けが考えられます。
GT7の走行データを取得する仕組みやPythonライブラリgt-telemについては、「GT7のテレメトリーデータは取得できる? Pythonで受信する仕組みを紹介」で紹介しています。受信したデータをCSVなどに保存したあと、分析の用途に応じてParquetへ変換する流れにつながります。
大切なのは、どちらが優れているかではなく、目的に合わせて使い分けることです。
まとめ
今回は、Parquetの基本的な仕組みとPythonを使ったファイルの作成方法を紹介し、GT7の実測データでも比較しました。
ポイントは次の3つです。
- Parquetは列指向のファイル形式で、同じ列のデータをまとめて保存する。
- 必要なチャンネルだけを効率よく読み込めるため、多チャンネルのレースデータ分析と相性がよい。
- Pythonを使えば、CSVからParquetへの変換も数行のコードで実現できる。
約20万行のGT7ログでは、Parquetで容量が約59〜68%小さくなり、列を絞った読み込みにも効果が見られました。環境やデータによって結果は変わるので、まずは自分がよく行う分析で試してみるのがおすすめです。
Parquetは最初こそ難しそうに感じるかもしれませんが、基本的な考え方はそれほど複雑ではありません。
まずは手元のCSVをParquetに変換して、ファイルサイズや読み込み方の違いを試してみると、理解が深まると思います。
参考資料
Parquetについてさらに詳しく知りたい方は、以下の公式ドキュメントも参考にしてください。
- Apache Parquet:概要 — Parquetの基本的な特徴を紹介しています。
- pandas:DataFrame.to_parquet() — Parquet形式での保存方法や圧縮設定を確認できます。
- pandas:read_parquet() — 読み込み方法や必要な列の指定を確認できます。
- Apache Arrow:PythonでのParquetの読み書き — 内部で使用しているPyArrowの読み書きや圧縮設定を詳しく確認できます。