本文へスキップ
PLUSSCODE

TECHNICAL JOURNAL

Pythonで参加者CSVを点検する|空欄・ID重複・人数の表記違いを見つける

受付名簿を作る前に、参加者CSVの必須欄、ID重複、人数の表記をPythonで確認します。架空データ10件の検証結果と、そのまま試せるコードを掲載。先頭ゼロを残す理由や、元ファイルを変更しない設計も説明します。

主カテゴリー:アプリ開発・システム運用

  • Python
  • CSV
  • 参加者名簿
  • 業務自動化

検証環境

  • Python 3.12.2
  • Windows 11(build 26200)
  • Python標準ライブラリのみ

イベントの申込みデータから受付名簿を作るときは、名前の並べ替えや印刷の前に、空欄や重複を確かめておきたいものです。たとえば、同じ参加者IDが二度出てきても、二重申込みなのか、申込み内容を更新した結果なのかは、CSVだけでは分かりません。担当者が判断するためには、まず該当するデータを見つける必要があります。

そこで、元のCSVを変更せず、確認が必要な箇所だけを表示するPythonの小さなプログラムを作りました。架空データ10件を使い、必須欄の空欄、参加者IDの重複、人数欄に混ざった文字や小数表記を点検します。追加ライブラリは使いません。

対象は、参加者データの整理を担当し、Pythonのファイルを保存して実行したことがある方です。本文のCSVとコードを手元に保存すれば、同じ結果を確かめられます。自動修正の前に、何を問題として扱うかを決めるところから始めましょう。

目次

課題:人数は数として、参加者IDは文字列として確かめる

今回のCSVには、参加者ID、名前、人数の3列を用意します。一つの申込みに複数人が含まれる想定で、人数を party_size としました。顧客の名簿ではなく、動作確認用に作った架空のデータです。

人数が 2、二、2.0 と書かれていれば、人は同じ人数を表していると読めるかもしれません。ただ、次に取り込むシステムが半角の整数を求めるなら、表記を確認する必要があります。今回は「1以上の整数を、先頭に0を付けず半角数字で書く」と決め、条件に合わない値を表示します。

一方、参加者IDの 001 は識別のための記号です。数値へ変換して 1 にすると、元の表記を失います。Pythonの csv.reader は、通常の読込みでは各欄を文字列として返します。今回は数値に変換せず、前後の空白だけを除いて比較します。001 と 1 は別のIDとして扱う設計です。Python公式のCSV読込み仕様

よく「型混在」と呼ばれる状態も、CSVを読んだ時点では文字列同士の違いです。この例では、人数欄に適用する表記ルールを明示して、そこから外れる値を見つけます。

検証条件:意図的に問題を入れた10件を3回点検する

2026年9月27日に、Windows 11(build 26200)、Python 3.12.2で実行しました。CSVはUTF-8で保存し、ヘッダーを除く10件を同じコードで3回読み込みました。確認したのは、出力が期待した内容と一致することと、入力ファイルの内容が変わらないことです。処理時間や、現場での作業時間の削減は測定していません。

3列すべてを必須にします。判定時は前後の空白を除き、空になった欄を「空欄」と数えます。この処理は読込み後の値に対して行い、CSVには書き戻しません。重複IDは2回目以降のデータを指摘し、最初に出現した通番も添えます。

入力の一部には、名前の空欄や、同じIDを持つ別の名前を入れました。人数欄には 二、2.0、空欄、0、全角の 2 を置き、先ほどのルールで見つけられるかを確かめます。

結果:空欄2件、重複1件、人数の表記違い4件を検出した

3回とも、表1の結果になりました。通番はヘッダーの次を1件目として数えています。

表1:架空データ10件に入れた問題と、プログラムの出力

確認項目 期待した件数 実際の件数(各回) 対象の通番
必須欄の空欄 2 2 3、7
参加者IDの重複(2回目以降) 1 1 4
人数の表記ルールに合わない値 4 4 5、6、9、10

この入力では、予定していた7件の指摘をすべて確認でき、余分な指摘はありませんでした。対象データも7件です。人数の空欄は最初の項目だけで数え、表記違いとして重ねて数えていません。別のCSVで一つのデータに複数の問題があれば、指摘件数と対象データ数は異なります。

入力ファイルについても、実行前後で内容から計算する照合値(SHA-256)が一致しました。ただし、これは用意した小さな入力での確認です。未知の名簿でも検出漏れや誤検出がない、という結果ではありません。

再現手順:CSVとコードを同じフォルダーに保存する

架空のCSVを用意する

作業用の空のフォルダーを作り、次を participants.csv という名前でUTF-8保存してください。本文と同じ文字を保存するため、テキストエディターを使います。8件目の人数には、判定時に前後の空白を無視することを確かめるため、3 の前に半角スペースを入れています。

participant_id,name,party_size
001,SAMPLE-A,1
002,SAMPLE-B,2
003,,1
002,SAMPLE-C,3
004,SAMPLE-D,二
005,SAMPLE-E,2.0
006,SAMPLE-F,
007,SAMPLE-G, 3
008,SAMPLE-H,0
009,SAMPLE-I,2

検査コードを保存して実行する

同じフォルダーに、次のコードを check_participants.py としてUTF-8保存します。コードは入力を読込み用に開き、結果を画面に表示します。CSVの出力処理や、外部への通信処理は含めていません。

"""Inspect a fictional participant CSV without modifying or printing its values."""

import argparse
import csv
import re
import sys
from pathlib import Path

FIELDS = ["participant_id", "name", "party_size"]


def inspect_csv(path):
    issues = []
    seen = {}
    count = 0
    with Path(path).open(encoding="utf-8-sig", newline="") as source:
        reader = csv.reader(source, strict=True)
        if next(reader, None) != FIELDS:
            raise ValueError("header must be participant_id,name,party_size")
        for count, cells in enumerate(reader, start=1):
            if len(cells) != len(FIELDS):
                raise ValueError(f"record {count}: expected 3 columns")
            row = dict(zip(FIELDS, (cell.strip() for cell in cells)))
            for field in FIELDS:
                if not row[field]:
                    issues.append((count, field, "missing"))
            participant_id = row["participant_id"]
            if participant_id:
                if participant_id in seen:
                    first = seen[participant_id]
                    issues.append(
                        (count, "participant_id", f"duplicate(first={first})")
                    )
                else:
                    seen[participant_id] = count
            size = row["party_size"]
            if size and re.fullmatch(r"[1-9][0-9]*", size) is None:
                issues.append((count, "party_size", "invalid_integer"))
    return count, issues


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("csv_path", type=Path)
    args = parser.parse_args()
    try:
        count, issues = inspect_csv(args.csv_path)
    except (OSError, UnicodeError, csv.Error, ValueError) as error:
        print(f"inspection failed: {error}", file=sys.stderr)
        return 2
    affected = len({record for record, _, _ in issues})
    print(f"records={count} issues={len(issues)} affected_records={affected}")
    for record, field, rule in issues:
        print(f"record={record} field={field} rule={rule}")
    return 1 if issues else 0


if __name__ == "__main__":
    raise SystemExit(main())

strip() は判定用の値の前後から空白を除く処理です。人数を調べる re.fullmatch() は、値全体が指定したパターンに一致するかを確認します。ここでの [1-9][0-9]* は「最初の1文字が1〜9、その後は0〜9が0文字以上続く」という条件です。空白を除く処理の仕様、値全体を照合する処理の仕様

作業フォルダーでターミナルを開き、次を実行します。Windowsで python が見つからない場合は、Pythonをインストールした際の実行環境を確認してください。

python --version
python check_participants.py participants.csv

期待する出力は次のとおりです。

records=10 issues=7 affected_records=7
record=3 field=name rule=missing
record=4 field=participant_id rule=duplicate(first=2)
record=5 field=party_size rule=invalid_integer
record=6 field=party_size rule=invalid_integer
record=7 field=party_size rule=missing
record=9 field=party_size rule=invalid_integer
record=10 field=party_size rule=invalid_integer

最初の行は、読んだデータが10件、指摘が7件、指摘されたデータが7件という意味です。duplicate(first=2) は「2件目と同じIDが再び出た」という表示です。名前やIDそのものは結果に表示せず、担当者が元CSVの該当箇所を確かめる形にしています。

今回は確認対象があるため、終了コードは1になります。0なら指摘なし、2なら文字コードや列構成などの理由で点検を完了できなかった状態です。2が返った場合は「問題なし」と扱わず、エラー表示を確認してください。

限界:重複を見つけても、残す申込みまでは決められない

このコードは、IDが重複した理由や、名前の正しさを判断できません。キャンセル済みの申込みや、人数の上限も見ていません。2 や 2.0 を許可する運用であれば、今回の人数ルールをそのまま適用することもできません。

入力はUTF-8と指定の3列に限定しています。列名や順序が違うファイルは停止します。また、すべてのCSV形式の誤りを検出するものではなく、大量データでの速度やメモリ使用量も未検証です。引用符内の改行を含む場合、出力するデータの通番と、エディター上の行番号は一致しません。

まずは架空データの人数を一つ書き換え、どの表示が変わるかを試してみてください。そのうえで実際の名簿へ応用する際は、申込みを管理する担当者と「必須の欄」「同じ申込みとみなすID」「受け付ける人数の表記」を確認します。どの値を直すか判断できる状態を作ってから、自動修正の範囲を考えると、元の情報を失う変更を避けやすくなります。

制作について:本記事は、資料の調査、構成案の作成、執筆・校正に生成AIを使用しています。検証した内容と確認できていない範囲を本文に示し、当社担当者の公開承認を経て掲載しています。

出典・参考資料

執筆者

IT事業部

Web開発からAIの利活用まで、イベントや日々の業務を支える仕組みづくりに取り組んでいます。事業会社でデータ活用の推進に携わるメンバーが、海外事例や技術の検証を通じて得た気づきを共有します。

IT事業の支援内容を見る

ご相談について

ご相談・お問い合わせ

Web開発やAIの活用、イベント運営に関するご相談を承ります。ご依頼やサービスについてのご質問は、お問い合わせフォームよりご連絡ください。

お問い合わせフォームへ