前回と今回のCSVで行の順番が違うだけなのに、変更箇所が大量に出ることがあります。行番号を基準にすると、別のID同士を比べてしまうためです。明細を識別できるIDがあるなら、それを基準にそろえます。
pandasのcompareは同じ行と列のラベルを持つ二つの表から違いを出す道具です。追加・削除のIDを先に分け、両方にあるIDだけを同じ順で並べてから、変更したセルを比べます。
追加と削除を比較の前に分ける
下の架空表では、Aの値は同じ、Bは200から250へ変更、Cは削除、Dは追加という条件です。set_indexのverify_integrityでIDの重複も検査します。
import pandas as pd
before = pd.DataFrame({
"ID": ["A", "B", "C"], "金額": [100, 200, 50]
}).set_index("ID", verify_integrity=True)
after = pd.DataFrame({
"ID": ["B", "A", "D"], "金額": [250, 100, 90]
}).set_index("ID", verify_integrity=True)
added = sorted(after.index.difference(before.index).tolist())
deleted = sorted(before.index.difference(after.index).tolist())
common = sorted(before.index.intersection(after.index).tolist())
columns = ["金額"]
delta = before.loc[common, columns].compare(
after.loc[common, columns], result_names=("前", "後")
)
print("追加ID:", added)
print("削除ID:", deleted)
print("変更ID:", delta.index.tolist())
print("Bの金額:", int(delta.loc["B", ("金額", "前")]), "→", int(delta.loc["B", ("金額", "後")]))
assert added == ["D"] and deleted == ["C"]
assert delta.index.tolist() == ["B"]
追加はD、削除はC、共通ID内の変更はBだけです。Aは行の位置が変わっていても、変更として出ません。Windows・Python 3.12.10・pandas 3.0.2で、この分類と金額の前後を確認しました。
比較列を複数へ増やす場合も、両方に必要な列があるかを先に確認します。列がない状態を空の値で埋めてしまうと、入力形式の変更とセルの変更を混ぜてしまいます。
同じIDだと言える条件を決める
IDが空欄なら、行を正しく対応させられません。前後の空白、先頭ゼロ、大文字小文字なども、読み込み時の解釈をそろえます。値を似せることを優先して、別のIDまで同じものへ変換しないようにします。
同じIDの行が複数ある業務なら、枝番や日付を含む複合キーが必要になる場合があります。一意性のエラーを消すために一行を残す処理へ変える前に、一件の単位を確かめてください。
compareの前提は、比較する表の形とラベルが一致することです。追加や削除を含む二つの表を、そのまま渡してすべての差を出す機能ではありません。
差がないことの意味を確認
同じ場所の欠損値同士はcompareでは変更として出ません。未入力が続いていることを確認したい場合は、変更表とは別の欠損検査も必要です。
文字列の200と数値の200を同じと扱うか、空文字と欠損を同じと扱うかも、業務の定義に依存します。比較の前に型や空欄をそろえるなら、元の値を残し、どんな変換を行ったかが分かる形にします。
出力は確認用の差分です。追加IDが見つかったことを根拠に、別の台帳へ自動登録したり、削除IDを本番から消したりする処理は含んでいません。前回と今回の入力を別名で残し、差の理由を確認してから次の操作へ進めます。
前後のデータを比べる設計は差分収集の基本、表の扱いはpandas入門で確認できます。
参考資料
pandas.DataFrame.compare公式資料を2026年11月1日に確認しました。
