【実測】CSVファイル1,000個(50,000行)の結合、Pythonなら平均59.45秒だった|100個の10倍にはならない?
CSVファイル1,000個(合計50,000行)を1つのExcelファイルに結合したところ、3回実測の平均は59.45秒でした。前回検証した100個(平均3.8秒)の「ちょうど10倍の38秒」にはならず、平均同士の比較では約15.6倍(59.45÷3.8)という結果です。
ただし中身を見ると話は単純ではありません。最も遅かった1回目は104.37秒、最速の2回目は32.31秒と大きな差があり、その理由も工程別の実測から見えてきました。この記事では、使ったスクリプトの全文、3回分の実測結果と前回との比較、つまずきやすいポイントまで、手元で検証した内容だけを書きます。
前回のおさらい:100個なら平均3.8秒だった
前回の記事では、CSVファイル100個(合計5,000行)を1つのExcelに結合して、同じPCで3回実測しました。結果は1回目6.2秒/2回目3.4秒/3回目1.9秒で、平均3.8秒。「コピペ1回でスクリプトを用意すれば、あとは数秒」という結論でした。
そこで今回の問いはこうです。ファイル数を10倍の1,000個(行数も10倍の50,000行)にしたら、時間も10倍の約38秒(3.8秒×10の単純計算)で済むのか? 「データ量に比例して時間が延びるだけなら怖くない」のか、それとも「量が増えると別の壁が出てくる」のか。実測で確かめました。
検証環境とデータ内容
実測に使った環境とデータは次のとおりです。
- OS: Windows 11 Pro(ビルド 10.0.26200)
- Python: 3.12.10(venv環境)
- pandas: 3.0.5 / openpyxl: 3.1.5
- 入力ファイル: CSVファイル1,000個(sales_0001.csv〜sales_1000.csv)、合計50,000行(1ファイルあたり50行)
- 列構成: 日付/商品名/数量/単価/金額の5列
- データ内容: 文房具の売上ダミーデータ
前回と同じなのは、PC・列構成・「読み込み→結合→Excel保存」というスクリプトの流れです。変えたのはファイル数(100個→1,000個)と合計行数(5,000行→50,000行)だけです。
なお、入力CSVはローカルのTempフォルダ(OneDrive同期の対象外)に置いて実行しました。OneDrive配下だと同期処理の影響でさらに遅くなる可能性があります(こちらは未計測です)。
スクリプト全文と使い方
以下が実測に使ったスクリプトの全文です。pandas(表形式のデータをPythonで扱うための定番ライブラリ)で読み込み・結合し、Excel形式で保存します。工程ごとの時間も表示するようにしてあります。
# CSVファイル1,000個を1つのExcel(まとめ.xlsx)に結合するスクリプト
import time
from pathlib import Path
import pandas as pd
# CSVが入っているフォルダ(自分の環境に合わせて変更してください)
INPUT_DIR = Path(r"C:\Users\あなたの名前\Desktop\csvフォルダ")
OUTPUT_FILE = INPUT_DIR.parent / "まとめ.xlsx"
start = time.perf_counter()
# 1. CSVを全部読み込む(どのファイル由来か分かるよう「元ファイル名」列を追加)
dfs = []
for csv_file in sorted(INPUT_DIR.glob("*.csv")):
df = pd.read_csv(csv_file, encoding="utf-8-sig")
df["元ファイル名"] = csv_file.name
dfs.append(df)
read_done = time.perf_counter()
# 2. 1つの表に結合
merged = pd.concat(dfs, ignore_index=True)
concat_done = time.perf_counter()
# 3. Excelファイルに保存
merged.to_excel(OUTPUT_FILE, index=False)
end = time.perf_counter()
print(f"ファイル数: {len(dfs)}")
print(f"行数: {len(merged)}")
print(f"読み込み: {read_done - start:.2f}秒")
print(f"結合: {concat_done - read_done:.2f}秒")
print(f"Excel保存: {end - concat_done:.2f}秒")
print(f"合計: {end - start:.2f}秒")
使い方(3ステップ)
- 上のコードを「merge_csv.py」などの名前で保存します
- 冒頭の
INPUT_DIRを、結合したいCSVが入っているフォルダのパスに書き換えます - コマンドプロンプト(Windowsの黒い画面)で
python merge_csv.pyと入力して実行します
実行が終わると、CSVフォルダの1つ上の階層に「まとめ.xlsx」が作られます。ポイントは「元ファイル名」列の追加です。結合後の表を見たとき、どの行がどのCSV由来か後から追跡できます。
実測結果:3回の計測(工程別の内訳つき)
同じ処理を3回連続で実行した結果です。今回は工程別の時間も記録しました。
| 実行回 | 読み込み | 結合 | Excel保存 | 合計 |
|---|---|---|---|---|
| 1回目 | 64.16秒 | 0.23秒 | 39.98秒 | 104.37秒 |
| 2回目 | 4.79秒 | 0.17秒 | 27.36秒 | 32.31秒 |
| 3回目 | 4.63秒 | 0.20秒 | 36.85秒 | 41.68秒 |
| 平均 | 59.45秒 |
前回(100個)との比較
| 実行回 | 前回:100個(5,000行) | 今回:1,000個(50,000行) | 倍率(計算値) |
|---|---|---|---|
| 1回目 | 6.2秒 | 104.37秒 | 約16.8倍 |
| 2回目 | 3.4秒 | 32.31秒 | 約9.5倍 |
| 3回目 | 1.9秒 | 41.68秒 | 約21.9倍 |
| 平均 | 3.8秒 | 59.45秒 | 約15.6倍 |
冒頭の問い「10倍の量なら10倍の時間?」への答えは、平均では約15.6倍で、きっちり10倍にはならなかった、です。ただし回ごとのぶれが大きく、2回目だけを見れば約9.5倍とほぼ比例どおりでした。このぶれの正体を次で見ていきます。
出力の中身も検証しました
速くても結果が壊れていては意味がないので、出力された「まとめ.xlsx」をopenpyxl(ExcelファイルをPythonで直接読み書きするライブラリ)で検証しました。
- 総行数はヘッダ含め50,001行(=データ50,000行)で期待どおり、列は「日付/商品名/数量/単価/金額/元ファイル名」の6列
- 「元ファイル名」のユニーク数(重複を除いた種類数)は1,000で、全ファイル分が結合されている
- 先頭データ行(2026-01-10、クリアファイル、5個×55円=275円、sales_0001.csv)と最終データ行(2026-05-11、修正テープ、20個×198円=3,960円、sales_1000.csv)で「金額=数量×単価」の整合も確認
- 出力ファイルサイズは約1.9MB
考察:時間はどこに消えたのか
1回目だけ読み込みが約13倍遅い
工程別の表を見ると、1回目の読み込みは64.16秒、2回目以降は4.7秒前後と、約13倍の差があります。これは、ファイル生成直後の初回アクセスではOSのファイルキャッシュ(一度読んだファイルの内容をメモリに覚えておく仕組み)が効いておらず、1,000ファイル分のディスク読み込みと、Windowsのリアルタイムスキャン(セキュリティ機能によるファイル検査)が乗ったためとみられます。
つまり平均59.45秒には初回のこの影響が含まれています。キャッシュが効いた2〜3回目だけの平均なら37.0秒で、前回の2〜3回目平均2.65秒((3.4+1.9)÷2)と比べると約14倍です。
キャッシュが効いた後の主役は「Excel保存」
2回目以降の内訳を見ると、Excel保存が27〜37秒で合計の8割超を占めています。一方、pandasのconcat(表同士の結合)は50,000行でも0.2秒程度で、ほぼ無視できる速さでした。ファイル数が増えたときのボトルネックは「1,000個を読むこと」ではなく「1つの大きなExcelに書き出すこと」だった、というのが今回の発見です。
50,000行はExcelの上限にはまだ余裕
Excelの1シートの上限は1,048,576行なので、50,000行は余裕があります。ただし、保存時間を短くしたいなら、出力をExcelではなくCSVにする方がずっと速いはずです(今回は未計測のため、数値としては主張しません。次々回以降の検証候補です)。
つまずきポイント(大量ファイルならでは)
「まとめ.xlsx」を開いたまま再実行しない
出力先のExcelファイルを開いたままスクリプトを実行すると、Windowsではファイルが使用中のため保存に失敗し、エラー(PermissionError)で止まります。今回は保存だけで30秒前後かかるため、「待っている間に前回の結果を開いて眺めていたら、再実行が失敗した」が起きやすい構図です。再実行前に必ず閉じてください。
入力フォルダに関係ないCSVを混ぜない
このスクリプトはフォルダ内の「*.csv」を全部読みます。列構成の違うCSVが1個でも混ざると、エラーにはならずに列が横に増えて空欄だらけの表になり、一見成功したように見えて集計が狂います。ファイルが1,000個もあると目視での確認は現実的でないので、「結合用フォルダには対象のCSVだけを入れる」運用にするのが安全です。
文字コードのエラーが出たら
スクリプトでは encoding="utf-8-sig" を指定しています。Excelの「名前を付けて保存」で作った昔ながらのCSV(Shift_JIS形式)を読むとUnicodeDecodeErrorになることがあり、その場合は encoding="cp932" に書き換えてください。
1回目が遅くても異常ではない/OneDrive配下は避ける
前述のとおり1回目は104.37秒と突出して遅くなりましたが、2回目以降は32〜42秒に落ち着きました。初回だけ遅いのは故障ではありません。また、今回はOneDrive同期外のローカルフォルダで実行しています。同期フォルダ内だと同期処理でさらに時間がかかる可能性があります(未計測)。
まとめと次回予告
- CSV1,000個(50,000行)→Excel1つの結合は、3回実測の平均59.45秒(最遅104.37秒/最速32.31秒)
- 前回の100個(平均3.8秒)との比較では約15.6倍で、「10倍の量=10倍の時間」よりは重かった
- 内訳を見ると、初回はファイル読み込み(64.16秒)、2回目以降はExcel保存(27〜37秒、8割超)が支配的。結合そのものは0.2秒程度
- 出力は行数・列構成・元ファイル名の網羅・金額の整合まで検証して問題なし
1,000個でも「実行して1〜2分待てば終わる」水準であることは確認できました。手作業で1,000個のCSVを開いてコピペすることを考えれば、比較にならない差です。次回は、CSVではなくExcelブックの全シート結合(月別シートに分かれたブックを1枚にまとめる)を同じ形式で実測する予定です。
コメント
コメントを投稿