はじめに
Databricks / SparkでデータフレームをCSVファイルに出力する際、df.toPandas().to_csv()とdf.write.csv()のどちらを使うべきか迷うことがあります。この記事では、両者の違いと使い分けの基準を解説します。
選択の基準
データ量と出力先の要件で判断します。
df.toPandas().to_csv()を使う場合
適用ケース
小規模データ(数万〜数十万行程度)
メリット
- 単一のCSVファイルとして出力される
- Pandasの細かい制御が使える(フォーマット指定など)
- ローカル環境やExcelでそのまま扱いやすい
デメリット
- Sparkクラスタの全データをドライバーノードのメモリに集約する必要がある
- 大規模データではメモリ不足(OOM)が発生するリスクが高い
- 分散処理の利点が失われる
推奨される場面
- 分析結果の少量データを手元で確認したい
- データサイズがメモリに収まる範囲内
コード例
# Pandasに変換してCSV出力
df.toPandas().to_csv("output.csv", index=False)
df.write.csv()を使う場合
適用ケース
大規模データ(数百万行以上)
メリット
- Sparkの分散処理をそのまま活用できる
- メモリ制約を受けにくい
- S3やADLSなどの分散ストレージに直接書き込み可能
- モード指定(
overwrite、appendなど)やパーティション分割に対応
デメリット
- デフォルトでは複数ファイル(
part-0000x.csv形式)に分割される - 単一ファイルにする場合は
coalesce(1)やrepartition(1)が必要だが、処理速度が低下する
推奨される場面
- 本番環境でのデータ出力
- 大量データを安定的に処理したい
- 分散ストレージへの保存が必要
コード例
# 基本的な書き出し(複数ファイルに分割される)
df.write.mode("overwrite").option("header", "true").csv("output_path")
# パーティション分割して書き出し
df.write.mode("overwrite").option("header", "true").partitionBy("date").csv("output_path")
単一ファイルとして出力したい場合
Sparkで単一CSVファイルを作成する方法:
df.coalesce(1).write.mode("overwrite").option("header", "true").csv("output_path")
注意点
-
coalesce(1)は全データを1つのパーティションに集約するため、処理が遅くなる - データ量が多い場合はドライバーノードへの負荷が大きくなる可能性がある
- 出力されるファイル名は
part-00000-xxxxx.csvのような形式になる
単一ファイル名を指定したい場合
# 一時パスに出力後、リネームする方法
temp_path = "temp_output"
df.coalesce(1).write.mode("overwrite").option("header", "true").csv(temp_path)
# ファイルシステム操作でリネーム(DBFSの場合)
dbutils.fs.mv(f"{temp_path}/part-00000-*.csv", "output.csv")
まとめ
| 条件 | 推奨方法 | 理由 |
|---|---|---|
| 小規模データ(メモリに収まる) | df.toPandas().to_csv() |
単一ファイル出力が簡単、Pandas操作が使える |
| 大規模データ(分散処理が必要) | df.write.csv() |
メモリ効率が良い、スケーラブル |
| 単一ファイルが必要 | df.coalesce(1).write.csv() |
パフォーマンスとのトレードオフに注意 |
データ量の目安としては、数十万行を超える場合はdf.write.csv()を推奨します。