先に、答え。

最初のCSVのヘッダーを基準にし、後続ファイルの列名・列順が完全に一致するか確認してからデータ行だけを追加します。横方向の結合ではありません。

この記事の内容

対象・検証範囲:CPython 3.12.14 / Linux。掲載サンプルと期待する出力を照合。標準ライブラリのみ。

どんな結合に使えるか

同じ形式で出力されたファイルを、上から順に積み重ねる縦結合の例です。IDを照合して別の列を付け足す結合には使いません。

前提は、すべてのCSVに1行のヘッダーがあり、列名・列順が同じこと。データは文字列として保持し、同じ行が複数ファイルにあっても勝手に削除しません。空のファイルやヘッダーの違いが見つかったら、出力を作る前に止めます。

2つの入力を結合するコード

次の例は、文字列として読み込んだCSVのリストを受け取ります。空行は読み飛ばしますが、列数の違うレコードはエラーにします。

import csv
import io

def merge_csv(texts):
    if not texts:
        raise ValueError("入力がありません")
    header = None
    data = []
    for file_no, text in enumerate(texts, start=1):
        rows = csv.reader(io.StringIO(text, newline=""), strict=True)
        current = next(rows, None)
        if not current or len(set(current)) != len(current):
            raise ValueError(f"入力{file_no}: 空または重複ヘッダー")
        if any(not name.strip() for name in current):
            raise ValueError(f"入力{file_no}: 空の列名")
        if header is None:
            header = current
        elif current != header:
            raise ValueError(f"入力{file_no}: ヘッダー不一致")
        for record in rows:
            if not record:
                continue
            if len(record) != len(header):
                raise ValueError(f"入力{file_no}: 列数不一致")
            data.append(record)
    output = io.StringIO(newline="")
    writer = csv.writer(output, lineterminator="\n")
    writer.writerow(header)
    writer.writerows(data)
    return output.getvalue()

result = merge_csv(["id,name\n001,ノート\n", "id,name\n002,ペン\n"])
print(result, end="")
try:
    merge_csv(["id,name\n001,ノート\n", "name,id\nペン,002\n"])
except ValueError as error:
    print(error)

期待する結果とファイルでの使い方

id,name
001,ノート
002,ペン
入力2: ヘッダー不一致

ヘッダーは1回だけ出力され、IDの先頭ゼロも残ります。2回目の呼び出しは列順を入れ替えた入力で、意図どおり止まることを確認しています。

実ファイルではpathlib.Pathread_text(encoding="utf-8-sig")などで各ファイルを読み、文字列のリストをmerge_csv()へ渡します。返った文字列は新しいファイルをopen("merged.csv", "x", encoding="utf-8", newline="")で開き、write()で保存します。

入力順が必要なら、ファイル名の並びが期待どおりかを明示的に確認してください。1.csv, 10.csv, 2.csvの文字列順は、数値の順とは違います。出力ファイルを入力フォルダーへ置くと、次回の一括読み込みに混ざるので、入力と出力を分けます。

件数で結合を確かめる

結果のデータ件数は、各入力のデータ件数を合計したものと一致させます。ただし、ヘッダーと読み飛ばした空行を数えないこと。セル内改行があるCSVでは、物理的な行数で数えると合いません。

同じIDが重なる場合、それは結合の失敗とは限りません。「残す・削除する・内容を比べて止める」のどれが必要かは業務上のルールです。重複処理の例を使う前に、何を同一とみなすか決めてください。

制限とエラーの意味

この実装は全データをメモリーに保持します。巨大ファイル向けのストリーミング処理ではありません。列名の前後の空白も区別するので、idid は不一致です。違いを無視して結合する前に、出力元の仕様を確かめます。

途中のデータ行にヘッダーと同じ文字列が混入していても、自動では削除しません。本物の値との区別がつかないためです。構造確認にはCSVの検査を併用します。

参考にした公式資料

掲載サンプルは記載のPython環境で実行確認しています。すべてのOS・入力データを保証するものではありません。 編集・検証方針