商品マスターや顧客名簿、注文一覧を管理していると、「同じ商品が2回登録されている」「同じ顧客IDが複数行ある」といった重複が入り込むことがあります。
例えば、月ごとの商品一覧を1つにまとめたあとに同じ商品コードが2行できたり、顧客リストを統合したら同じ顧客が重複していたりするケースです。
数十行程度なら目で探せますが、数百行・数千行ある表から、
「A001が2回入っていないか」
「同じ注文番号が重複していないか」
を毎回確認するのはかなり大変です。
この記事では、Google ColabとPythonを使って、商品リストや顧客リストなどから重複している行を自動で見つけ、必要に応じて1件だけ残して削除する方法を紹介します。
完全に同じ行だけでなく、
商品コードは同じだが、価格や在庫数は違う
といった「確認が必要な重複候補」も見つけられます。
PythonをPCへインストールする必要はありません。Google Colabをブラウザで開き、CSVをアップロードしてコードを実行するだけです。
「重複していないか毎回目で探す作業をやめたい」人向けの記事です。
✅ この記事は実際に動作検証しています
Google ColabでCSVの重複データを抽出し、完全一致の重複と特定キーによる重複を確認しました。削除前に対象データを表示し、最初のデータを残す場合と最後のデータを残す場合の違いも検証しています。
検証結果: 重複抽出:成功 / 完全一致・キー重複を確認 / keep=first・keep=lastを検証 / 削除前の対象確認を実施
- この記事はこんな人向け
- この記事でできるようになること
- 今回使う商品リスト
- Google Colabで商品リストを開く
- まず「まったく同じ行」を探す
- keep=False は「重複している行を全部見せる」という意味
- 「完全一致」と「同じ商品コード」は別物
- 商品コードが同じ行をすべて表示する
- 価格が違う商品コードで再テストしてみる
- 商品コードではなく顧客IDや注文番号でも使える
- どの商品コードが何件あるか確認する
- 重複を1件だけ残して削除する
- 最後に登録されている行を残すこともできる
- first と last はどちらを使えばいい?
- 重複を見つけたら、いきなり削除しない方が安全
- 商品コード+店舗の組み合わせで重複を探すこともできる
- 行全体が完全に同じものだけ削除するならもっと簡単
- 重複整理後の商品リストをCSVに保存する
- なぜ utf-8-sig を指定しているのか
- 自分の商品リストや顧客リストで使うときに変更する場所
- どんな仕事で使える?
- この方法だけでは見つけにくい重複もある
- まとめ
この記事はこんな人向け
- 商品マスターに同じ商品コードが複数ないか確認している
- 顧客名簿の顧客IDやメールアドレスの重複を探している
- 注文一覧で同じ注文番号が2回登録されていないか確認している
- 複数のCSVを1つにまとめたあと重複チェックをしている
- 削除する前に重複候補を一覧で確認したい
この記事でできるようになること
今回の方法では、まず重複している行だけを表示して中身を確認します。
そのうえで、「商品コードが同じものを1件だけ残す」といった削除処理を行い、最後に重複整理後のCSVをダウンロードできる状態にします。
重複を探す
↓
内容を確認する
↓
どちらを残すか決める
↓
整理後のCSVを保存する
今回使う商品リスト
最初に、次のような商品一覧を用意しました。
| 商品コード | 商品名 | 価格 | 在庫 |
|---|---|---|---|
| A001 | 商品A | 1000 | 10 |
| A002 | 商品B | 1500 | 20 |
| A001 | 商品A | 1000 | 10 |
| A003 | 商品C | 2000 | 15 |
| A002 | 商品B | 1500 | 20 |
| A004 | 商品D | 1800 | 8 |
この商品一覧では、A001とA002がそれぞれ2回登録されています。
A003とA004は1回ずつです。

今回は products_duplicates.csv というファイル名で保存しています。
Google Colabで商品リストを開く
Google Colabで新しいノートブックを作成します。
今回はノートブック名を、
TaskLess Lab_CSV重複チェックテスト
としました。
左側のフォルダアイコンを開き、products_duplicates.csv をアップロードします。
そのあと、最初のコードセルに次を貼り付けます。
import pandas as pd
df = pd.read_csv("products_duplicates.csv")
display(df)
実行すると、商品コード・商品名・価格・在庫が表として表示されます。
ここではまだ重複を探していません。
まず、アップロードした商品リストをPythonが正しく読み込めているかを確認しています。
まず「まったく同じ行」を探す
最初に確認するのは、商品コード・商品名・価格・在庫がすべて同じ行です。
次のコードを実行します。
duplicates_all = df[df.duplicated(keep=False)]
display(duplicates_all)
今回の商品リストでは、A001とA002がそれぞれ完全に同じ内容で2回入っているため、4行が表示されます。

例えば、
A001 / 商品A / 1000円 / 在庫10
という行が2回入っていれば、2行とも表示されます。
keep=False は「重複している行を全部見せる」という意味
次の部分があります。
df.duplicated(keep=False)
keep=False を指定すると、重複している行の片方だけではなく、該当する行をすべて表示します。
どの行が重複しているのか確認したいときは、この方が分かりやすいです。
「完全一致」と「同じ商品コード」は別物
実際の商品マスターでは、もっと判断が難しいケースがあります。
例えば、
| 商品コード | 商品名 | 価格 | 在庫 |
|---|---|---|---|
| A001 | 商品A | 1000 | 10 |
| A001 | 商品A | 1200 | 8 |
のようなケースです。
どちらも商品コードはA001ですが、価格と在庫は違います。
そのため、行全体を比較すると「完全な重複」ではありません。
しかし商品マスターとして見ると、
なぜA001が2行あるのか確認したい
という状態です。
そこで次は、商品コードだけを基準に重複を探します。
商品コードの大文字・小文字や全角・半角が揃っていないと、本来同じデータでも重複として検出できないことがあります。

商品コードが同じ行をすべて表示する
次のコードを使います。
duplicates_code = df[
df.duplicated(
subset=["商品コード"],
keep=False
)
]
display(duplicates_code)
重要なのは、
subset=["商品コード"]
です。
これは、
商品コードが同じなら、ほかの列が違っていても重複候補として表示する
という指定です。

価格が違う商品コードで再テストしてみる
違いを分かりやすくするため、再テスト用の商品リストも作りました。
A001の片方を、
A001 / 商品A / 1200円 / 在庫8
に変更します。
これでA001は次の2行になります。
A001 商品A 1000 10
A001 商品A 1200 8
この状態で「完全一致」を探すと、A001は表示されません。
価格と在庫が違うためです。
完全一致しているA002だけが表示されました。

一方、商品コードだけで重複を確認すると、A001とA002の両方が表示されます。

この違いを理解しておくと、
- 完全に同じ行を消したいのか
- 同じ商品コードが複数あること自体を確認したいのか
を使い分けられます。
商品コードではなく顧客IDや注文番号でも使える
今回は商品マスターを例にしているため、
subset=["商品コード"]
としています。
顧客名簿なら、
subset=["顧客ID"]
注文一覧なら、
subset=["注文番号"]
JANコードを基準にするなら、
subset=["JANコード"]
のように変更できます。
つまり、subset には、この列が同じなら同じ対象として確認したいという列を指定します。
どの商品コードが何件あるか確認する
重複している行そのものではなく、「A001は何件あるのか」を確認したい場合は value_counts() を使います。
duplicate_counts = df["商品コード"].value_counts()
display(duplicate_counts)
今回なら、
A001 2
A002 2
A003 1
A004 1
のように表示されます。
2件以上ある商品コードだけに絞りたい場合は、
duplicate_counts_only = duplicate_counts[duplicate_counts > 1]
display(duplicate_counts_only)
とします。
これなら、
A001 2
A002 2
だけを確認できます。
重複を1件だけ残して削除する
重複内容を確認したあと、不要な行を削除してみます。
まずは、同じ商品コードが複数ある場合に、最初に出てきた1件を残す方法です。
deduplicated_df = df.drop_duplicates(
subset=["商品コード"],
keep="first"
)
display(deduplicated_df)
A001の場合、先に登録されている、
A001 / 商品A / 1000円 / 在庫10
が残ります。
後ろにある、
A001 / 商品A / 1200円 / 在庫8
は削除されます。
最後に登録されている行を残すこともできる
逆に、後ろの行を残したい場合は、
deduplicated_last_df = df.drop_duplicates(
subset=["商品コード"],
keep="last"
)
display(deduplicated_last_df)
とします。
今度は、
A001 / 商品A / 1200円 / 在庫8
が残ります。

first と last はどちらを使えばいい?
ここは機械的に決めない方が安全です。
例えば商品マスターなら、「最後の行の方が新しい価格だから last でいい」とは限りません。
CSVが並んでいる順番に、更新日の意味がない場合もあるからです。
今回の例では、first と last の違いを確認するために両方試しています。
実際の業務では、どちらの行が正しい情報なのかを確認したうえで削除する必要があります。
重複を見つけたら、いきなり削除しない方が安全
今回の再テストでは、
A001 商品A 1000 10
A001 商品A 1200 8
という2行がありました。
同じ商品コードですが、中身は違います。
商品コードだけを基準に drop_duplicates() を使えば、どちらか片方は削除できます。
しかし、1000円の商品情報を消すべきなのか、1200円の商品情報を消すべきなのかは、このCSVだけでは判断できません。
そのため、実務では、
まず重複候補を表示
↓
内容を確認
↓
残すルールを決める
↓
削除する
という流れの方が安全です。
商品コード+店舗の組み合わせで重複を探すこともできる
1つの列だけでは判断できないこともあります。
例えば同じA001でも、
東京店のA001
大阪店のA001
は別の在庫データとして扱いたいケースです。
その場合は、
subset=["商品コード", "店舗"]
のように複数列を指定できます。
これなら、商品コードと店舗の両方が同じ場合だけ重複と判断できます。
行全体が完全に同じものだけ削除するならもっと簡単
「商品コードが同じ」ではなく、すべての列が完全に同じ行だけ削除したいのであれば、
deduplicated_df = df.drop_duplicates()
だけでも対応できます。
この場合、
A001 / 1000円 / 在庫10
A001 / 1200円 / 在庫8
は別の行として残ります。
重複整理後の商品リストをCSVに保存する
今回は keep="first" で整理した結果を保存します。
deduplicated_df.to_csv(
"deduplicated.csv",
index=False,
encoding="utf-8-sig"
)
print("deduplicated.csv を作成しました")
実行すると、Colab左側のファイル一覧に、
deduplicated.csv
が表示されます。

ファイル右側のメニューからダウンロードすれば、Excelなどで開いて確認できます。
なぜ utf-8-sig を指定しているのか
保存コードでは、
encoding="utf-8-sig"
を指定しています。
これは、商品名や顧客名など日本語を含むCSVをExcelで開いたとき、文字化けしにくくするためです。
自分の商品リストや顧客リストで使うときに変更する場所
| 今回の設定 | 自分のファイルでは |
|---|---|
products_duplicates.csv | 実際のCSVファイル名 |
商品コード | 顧客ID、注文番号、JANコードなど |
keep="first" | 先頭を残すか最後を残すか |
deduplicated.csv | 保存したいファイル名 |
どんな仕事で使える?
今回の商品マスター以外にも、同じ考え方を使えます。
- ECの商品一覧でSKUやJANコードが二重登録されていないか確認する
- 顧客名簿で顧客IDやメールアドレスが重複していないか確認する
- 受注一覧で同じ注文番号が2回入っていないか確認する
- 複数店舗の商品一覧を1つにまとめたあと、同じ商品が重複していないか確認する
特に、毎月同じ形式の商品一覧や顧客一覧を更新している仕事では繰り返し使いやすい方法です。
この方法だけでは見つけにくい重複もある
今回の方法は、値が同じかどうかを基準にしています。
そのため、
株式会社ABC
(株)ABC
や、
山田太郎
山田 太郎
のように表記が少し違う場合は、別の値として扱われます。
電話番号でも、
03-1234-5678
0312345678
は、そのままでは同じ値として判定されません。
こうした「表記は違うが、実際には同じ人・同じ会社」というケースを探す場合は、文字の整形や名寄せなど別の処理が必要です。
重複だけでなく、新旧2つのCSVで価格や在庫の変更点を確認したい場合は差分比較が使えます。

まとめ
今回は、Google ColabとPythonを使って商品リストの重複をチェックしました。
完全に同じ行だけを探す方法と、商品コードだけを基準に重複候補を探す方法は別です。
また、重複が見つかったからといって、すぐに片方を削除していいとは限りません。
特に、
同じ商品コードなのに価格が違う
といったケースでは、どちらが正しい商品情報なのか確認する必要があります。
そのため、
重複候補を抽出する
↓
内容を確認する
↓
残すルールを決める
↓
重複を削除する
↓
整理後のCSVを保存する
という順番がおすすめです。
Google ColabならPythonをPCへインストールする必要もありません。
商品マスター・顧客名簿・注文一覧の「同じものが2回入っていないか」を目で探しているなら、その確認作業をかなり減らせます。


