Python講座 / pandasで表データを検証・集計する
pandasは表データをDataFrameとして扱うライブラリです。読み込み、検証、集計、保存を分け、不足値や不正値の扱いを示すと、合計にどの記録が含まれるか判断できます。
集計前に列の型を決める
DataFrameは表に相当する構造、Seriesは一つの列などを表します。CSVから推測された型は、業務の契約と一致するとは限りません。先頭の0を保つIDは文字列で読み、金額など必要な列だけを明示的に数値へ変換します。
プロジェクトの仮想環境へ導入します。pandasは外部パッケージなので、PythonとOSに対応する版を選びます。
python -m pip install pandas
検証と分類別集計の全体を実行する
pandas_demo.pyをUTF-8で保存し、python pandas_demo.pyを実行します。この例はファイルではなく、StringIOのCSV文字列を読みます。
from io import StringIO
import pandas as pd
raw = "id,category,amount\ne1,food,3500\ne2,food,8000\ne3,transport,2500\ne4,food,bad\n"
df = pd.read_csv(StringIO(raw), dtype="string", keep_default_na=False)
amounts = pd.to_numeric(df["amount"], errors="coerce")
valid = amounts.notna() & (amounts >= 0) & (amounts % 1 == 0)
clean = df.loc[valid].copy()
clean["amount"] = amounts.loc[valid].astype("int64")
report = clean.groupby("category", as_index=False, sort=True)["amount"].sum()
print("accepted:", len(clean), "rejected:", int((~valid).sum()))
for row in report.itertuples(index=False):
print(row.category, row.amount)
予想結果です。
accepted: 3 rejected: 1 food 11500 transport 2500
変換失敗と選択した表の意味を読む
errors="coerce"は変換できない値を不足値にします。不正なデータを黙って捨ててよいという意味ではなく、拒否を識別する方法です。validの条件と拒否件数を確認します。locで選択した後にcopyし、変換した列を独立した表へ設定します。
例の小さな金額はint64へ収まりますが、大きな整数や厳密な小数金額には精度と範囲の追加検証が必要です。数値条件だけで全レコードの妥当性は決まらず、空白、必須値、重複IDなどもデータ契約に応じて調べます。
保存して入力と照合する
reportを作ったファイルの末尾へ追加します。
report.to_csv("category-report.csv", index=False, encoding="utf-8")
to_csvは同名のファイルを置き換えるため、新しい保存先で実行します。index=FalseはDataFrameのインデックス列を省きます。有効な入力とレポートの合計がともに14000か確認します。
badを0へ変えて受理・拒否件数を比べ、-1へ変えて拒否を確認してから戻します。受理数と拒否数の合計も元の行数へ一致させます。pandasを必要としない小規模な処理には、標準ライブラリのCSV実習という選択肢もあります。
実際のCSVを読むにはDataFrame作成部分を pd.read_csv("expenses-input.csv", dtype={"id":"string", "category":"string", "amount":"string"}) に替え、その後に数値変換と有効マスクを適用します。除外行も別に残します。欠損を0で埋めると未入力と実際の0を区別できません。この練習の小さい整数という前提を超える金額には別の精度方針が必要です。




