pandas
では、DataFrame
やSeries
内の重複行を簡単に抽出、削除することができます。
しかし、実際に重複処理をしようとしても、次のような問題に直面することも…。
- そもそも重複行を抽出する方法は?
- 重複行を削除することはできるの?
- 特定の列が重複しているかを判定したい!
そこで、この記事ではpandas
の重複処理について、データ抽出、削除、重複行に連番を振る方法をわかりやすく・図解付きで解説していきます!
- pandas重複処理まとめ
- 重複列の判定・抽出|.duplicated()
- 重複行の削除|.drop_duplicates()
- インデックス列の重複判定
- 【応用編】重複行に連番を振る方法
- オススメ|pandasとデータ分析の勉強方法
pandas重複処理まとめ
DataFrame
の主な重複行の処理として、まずは次の3つを抑えておきましょう。
処理内容 | メソッド名 | 適用 |
---|---|---|
重複行の判定 | df.duplicated() |
データ列をもとに重複を判定 ※インデックス列は調査対象にならない |
重複行の削除 | df.drop_duplicates() |
同上、さらに対象行を削除 |
インデックス列の重複判定 | df.index.duplicated() |
インデックス列をもとに重複判定 |
図にしてみると、次のような対応関係になっています。
DataFrame
, Series
のメソッドでは、次のように重複判定を行います。
- データ列をもとに重複判定が行われる(インデックス列は重複判定に使用されない)
- 全てのデータ列が同じ場合のみ、重複行として判定される
インデックス列で重複判定する場合は、index
のメソッドを使用することに注意しましょう。
以下では、各重複処理について詳しく解説していきます。
重複列の判定・抽出|.duplicated()
重複列の判定には、.duplicated()
メソッドを使用します。
デフォルトでは、次のような挙動になります。
- 全てのデータ列が同じ値を持つ行がある場合に重複とみなされる
- 2回目以降に現れた重複行が
True
となるSeries
を返す
言葉ではわかりにくい部分もあるので、次のサンプルコードで挙動を確認してみましょう。
import pandas as pd
df = pd.DataFrame({"名前": ["田中", "田中", "田中", "伊藤", "田中"],
"注文": ["カレー", "寿司", "カレー", "寿司", "カレー"],
"値段": [1000, 1200, 1000, 1200, 1000]})
# 名前 注文 値段
# 0 田中 カレー 1000 ← 0, 2, 4行目が重複
# 1 田中 寿司 1200
# 2 田中 カレー 1000 ← 0, 2, 4行目が重複
# 3 伊藤 寿司 1200
# 4 田中 カレー 1000 ← 0, 2, 4行目が重複
デフォルト設定のまま、df.duplicated()
を実行してみます。
df.duplicated()
# 0 False ← 0, 2, 4行目が重複
# 1 False
# 2 True ← 0, 2, 4行目が重複
# 3 False
# 4 True ← 0, 2, 4行目が重複
# dtype: bool
重複している0, 2, 4行目のうち、2回目以降に現れる2, 4行目にのみTrue
を持つSeries
が返されました。
DataFrame
は真偽値のSereis
を渡すと、True
の行だけ抽出できるので、 df.duplicated()
をdf
に渡せば重複行を抽出できますね。
df[df.duplicated()]
# 名前 注文 値段
# 2 田中 カレー 1000
# 4 田中 カレー 1000
逆にFalse
行のみを抽出したい場合は、~
で真偽を反転させればOKです。
df[~df.duplicated()]
# 名前 注文 値段
# 0 田中 カレー 1000
# 1 田中 寿司 1200
# 3 伊藤 寿司 1200
重複行の削除は、後述のdf.drop_duplicated()
で生成することもできます。
以下で、df.duplicated()
の詳細設定について、解説していきます。
- 【参考】基本的なデータ抽出方法については、次の記事を参考にしてください。


.duplicated()の引数
.duplicated()
メソッドでは、引数を指定して次のような詳細設定を行うことができます。
設定内容 | 引数名 | 適用 |
---|---|---|
重複判定する列の指定 | subset="列名" or"列名のリスト" |
デフォルト:全列が同じだと重複と判定subset で調査列を指定可能 |
True を返す重複行の指定 |
keep="first" , or "last" , or False |
"first" (デフォルト):一個目以外の重複行でTrue"last" :最後以外の重複行でTrue False :全ての重複行でTrue |
以下で、サンプルデータを用いて挙動を確認してみます。
特定の列で重複判定|subset
.duplicated()
では、基本的に全ての列が同じ値を持っていると重複判定されます。
df
# 名前 注文 値段
# 0 田中 カレー 1000 ← 0, 2, 4行目が重複
# 1 田中 寿司 1200
# 2 田中 カレー 1000 ← 0, 2, 4行目が重複
# 3 伊藤 寿司 1200
# 4 田中 カレー 1000 ← 0, 2, 4行目が重複
# subsetの指定なしで重複行を出力
df[df.duplicated(keep=False)]
# 名前 注文 値段
# 0 田中 カレー 1000
# 2 田中 カレー 1000
# 4 田中 カレー 1000
※ ここでは重複判定結果がわかりやすいように、keep=False
で重複列全てを抽出しています(keep
については後述)。
全ての列ではなく、特定の列を指定して重複判定する場合には、引数subset
で列名を指定します。
- 重複判定する列を指定:
subset="列名" or ["列名"のリスト]
["列名"のリスト]
を指定すれば、指定した列が全て同じデータの場合のみ重複とみなされます。
subset="名前"
で、"名前"
列が重複している行を判定、抽出してみます。
# .duplicateメソッドで真偽値を出力
df.duplicated(subset="名前", keep=False)
# 0 False
# 1 True
# 2 False
# 3 True
# 4 True
# dtype: bool
# 重複行の抽出
df[df.duplicated(subset="名前", keep=False)]
# 名前 注文 値段
# 0 田中 カレー 1000
# 1 田中 寿司 1200
# 2 田中 カレー 1000
# 4 田中 カレー 1000
"注文"
列が異なっていても、"名前"
列が同じ行は重複として判定されましたね。
次に、"名前"
列と"注文"
列を指定してみます。
# .duplicateメソッドで真偽値を出力
df.duplicated(subset=["名前", "注文"], keep=False)
# 0 True
# 1 False
# 2 True
# 3 False
# 4 True
# dtype: bool
# 重複行の抽出
df[df.duplicated(subset=["名前", "注文"], keep=False)]
# 名前 注文 値段
# 0 田中 カレー 1000
# 2 田中 カレー 1000
# 4 田中 カレー 1000
今度は、"名前"
列と"注文"
列の両方が同じ行のみが重複行として認識されました。
重複でTrueを返す行の指定|keep
.duplicated()
のデフォルト設定では、最初に現れた重複行以外に対してTrue
を返します。
サンプルコードで挙動を確認してみましょう。
df
# 名前 注文 値段
# 0 田中 カレー 1000 ← 0, 2, 4行目が重複
# 1 田中 寿司 1200
# 2 田中 カレー 1000 ← 0, 2, 4行目が重複
# 3 伊藤 寿司 1200
# 4 田中 カレー 1000 ← 0, 2, 4行目が重複
df.duplicated()
# 0 False ← 0, 2, 4行目が重複(デフォルトでは、一つ目の重複行はFalse)
# 1 False
# 2 True ← 0, 2, 4行目が重複
# 3 False
# 4 True ← 0, 2, 4行目が重複
# dtype: bool
上の例では、0, 2, 4行目が重複しているので、2回目以降の重複である2, 4行目に対してTrue
が返されています。
この挙動は引数keep
で変更可能です。
引数の指定方法 | 設定内容 |
---|---|
keep='first' (デフォルト) |
最初に現れた重複行以外にTrue |
'last' |
最後に現れた重複行以外にTrue |
False |
全ての重複行にTrue |
サンプルコードで挙動を確認してみましょう。
# keep="first"(デフォルトなので、省略可能)
df.duplicated(keep="first")
# 0 False ← 0, 2, 4行目が重複(最初の重複行, Falseになる)
# 1 False
# 2 True ← 0, 2, 4行目が重複(2個目の重複行)
# 3 False
# 4 True ← 0, 2, 4行目が重複(最後の重複行)
# dtype: bool
# keep="last"
df.duplicated(keep="last")
# 0 True ← 0, 2, 4行目が重複(最初の重複行)
# 1 False
# 2 True ← 0, 2, 4行目が重複(2個目の重複行)
# 3 False
# 4 False ← 0, 2, 4行目が重複(最後の重複行, Falseになる)
# dtype: bool
# keep = False
df.duplicated(keep=False)
# 0 True ← 0, 2, 4行目が重複(最初の重複行)
# 1 False
# 2 True ← 0, 2, 4行目が重複(最初の重複行)
# 3 False
# 4 True ← 0, 2, 4行目が重複(最初の重複行)
# dtype: bool
なぜ引数名がkeep
なのかというと、これはdf.drop_duplicate()
と関係があります。
df.drop_duplicate()
では、引数keep
で指定した行が保持(keep)されるようになるためです。
重複行の削除|.drop_duplicates()
重複列の削除には、.drop_duplicates()
メソッドを使用します。
デフォルトでは、次のような挙動になります。
- 全てのデータ列が同じ値を持つ行がある場合に重複とみなされる
- 2回目以降に現れた重複行を削除した
DataFrame
orSeries
を返す
重複の判定等は.duplicated()
と類似した挙動ですね。
サンプルコードで挙動を確認してみましょう。
df
# 名前 注文 値段
# 0 田中 カレー 1000 ← 0, 2, 4行目が重複
# 1 田中 寿司 1200
# 2 田中 カレー 1000 ← 0, 2, 4行目が重複
# 3 伊藤 寿司 1200
# 4 田中 カレー 1000 ← 0, 2, 4行目が重複
df.drop_duplicates()
# 名前 注文 値段
# 0 田中 カレー 1000
# 1 田中 寿司 1200
# 3 伊藤 寿司 1200
最初に現れた重複行以外の重複行が削除されましたね。
.drop_duplicates()の引数
.drop_duplicates()
メソッドでは、引数を指定して次のような詳細設定を行うことができます。
設定内容 | 引数名 | 適用 |
---|---|---|
重複判定する列の指定 | subset="列名" or"列名のリスト" |
デフォルト:全列が同じだと重複と判定subset で調査列を指定可能 |
.drop_duplicates() 実行後に残す重複行の指定 |
keep="first" , or "last" , or False |
"first" (デフォルト):一個目の重複行を残す"last" :最後の重複行を残すFalse :全ての重複行を削除(残さない) |
インデックスの振り直し | ignore_index=False or True |
False (デフォルト): 振り直しなし True : 連番で振り直し |
df の上書き |
inplace=False or True |
False (デフォルト): 新規df を生成 True : 既存df を上書き |
.duplicated()
と類似した引数ですね。
重複行処理で特に重要なsubset
とkeep
、ignore_index
について、詳しく見ていきましょう。
特定の列で重複判定|subset
特定の列を指定して重複判定する場合には、引数subset
で列名を指定します。
- 重複判定する列を指定:
subset="列名" or ["列名"のリスト]
次のサンプルデータで挙動を確認してみましょう。
# "名前"列を指定
df.drop_duplicates(subset="名前")
# 名前 注文 値段
# 0 田中 カレー 1000
# 3 伊藤 寿司 1200
# ["名前", "注文"]を指定
df.drop_duplicates(subset=["名前", "注文"])
# 名前 注文 値段
# 0 田中 カレー 1000
# 1 田中 寿司 1200
# 3 伊藤 寿司 1200
subset
の指定方法がわかると、重複処理の自由度も上がってきますね
削除しない行の指定|keep
drop_duplicates
のデフォルトでは、一つ目の重複行を残して、二つ目以降の重複行が削除します。
この挙動は引数keep
で変更可能です。
引数の指定方法 | 設定内容 |
---|---|
keep='first' (デフォルト) |
最初の重複行を残す |
'last' |
最後の重複行を残す |
False |
全ての重複行を削除 |
実際にサンプルデータで挙動を確認してみましょう。
# keep="first"(デフォルトなので、省略可能)
df.drop_duplicates(keep="first")
# 名前 注文 値段
# 0 田中 カレー 1000 <-最初の重複行が残った
# 1 田中 寿司 1200
# 3 伊藤 寿司 1200
# keep="last"
df.drop_duplicates(keep="last")
# 名前 注文 値段
# 1 田中 寿司 1200
# 3 伊藤 寿司 1200
# 4 田中 カレー 1000 <-最後の重複行が残った
# keep = False:重複行が残らない
df.drop_duplicates(keep=False)
# 名前 注文 値段
# 1 田中 寿司 1200
# 3 伊藤 寿司 1200
インデックスの再設定
デフォルト挙動では、削除された行のインデックスは特段追加処理されることがありません。
そのため、drop_duplicates
によってインデックスが飛び飛びの数字になる場合があります。
df.drop_duplicates(keep="last")
# 名前 注文 値段
# 1 田中 寿司 1200
# 3 伊藤 寿司 1200
# 4 田中 カレー 1000
ignore_index=True
を指定すると、既存のインデックスを無視して、連番のインデックスを振り直すことができます。
df.drop_duplicates(ignore_index=True)
# 名前 注文 値段
# 0 田中 カレー 1000
# 1 田中 寿司 1200
# 2 伊藤 寿司 1200
既存のインデックス列がある場合も、連番を振り直すことができます。
df2 = df.copy()
df2.index = pd.Index(["001", "002", "003","004","005"], name="ID")
# 名前 注文 値段
# ID
# 001 田中 カレー 1000
# 002 田中 寿司 1200
# 003 田中 カレー 1000
# 004 伊藤 寿司 1200
# 005 田中 カレー 1000
df2.drop_duplicates(ignore_index=True)
# 名前 注文 値段
# 0 田中 カレー 1000
# 1 田中 寿司 1200
# 2 伊藤 寿司 1200
元のインデックス列が削除されて、連番のインデックスが振りなおされましたね。
- 【参考】欠損値の削除については、次の記事を参考にしてください。

インデックス列の重複判定
インデックス列の重複を判定する場合は、index
オブジェクトのメソッドを使います。
メソッド名はdf
と同様で.duplicated()
です。
df.index.duplicated()
インデックスが重複したサンプルデータを用意して挙動を確認してみましょう。
df3=df.set_index("名前")
# 注文 値段
# 名前
# 田中 カレー 1000
# 田中 寿司 1200
# 田中 カレー 1000
# 伊藤 寿司 1200
# 田中 カレー 1000
df.index.duplicated()
で、重複判定をしてみます。
df3.index.duplicated()
# array([False, True, True, False, True])
# 重複インデックスの抽出
df3[df3.index.duplicated(keep=False)]
# 注文 値段
# 名前
# 田中 カレー 1000
# 田中 寿司 1200
# 田中 カレー 1000
# 田中 カレー 1000
- インデックスの操作に関しては、次の記事で詳しく解説しているで参考にしてください

【応用編】重複行に連番を振る方法
重複行に連番を振る場合には、.groupby().cumcount()
で要素数を数えればOKです。
df.groupby("列名"など).cumcount()
これはDataFrame
ではなく連番のSeries
を返すだけなので、結果をdf
に渡したほうが見やすくなります。
df.groupby("名前").cumcount()
df["重複"]=df.groupby("名前").cumcount()
# 名前 注文 値段 重複
# 0 田中 カレー 1000 0
# 1 田中 寿司 1200 1
# 2 田中 カレー 1000 2
# 3 伊藤 寿司 1200 0
# 4 田中 カレー 1000 3
.groupby()
に関しては、次の記事で詳しく解説しているで参考にしてください

オススメ|pandasとデータ分析の勉強方法
今回はpandas
の重複処理について図解付きで解説しました。
pandas
は便利すぎて操作方法がわかりにくいことがよくあります…。
結局はコツコツ学ぶのが、pandas
マスターの近道ですよね!
データ分析初心者の方にはこちらの記事もおススメです。
私がこれまで勉強してきた経験をもとに考えたおススメの勉強本の紹介記事です。
何から始めて、どうやってレベルアップしていけばいいのか、初心者の方にぜひおススメしたい本を紹介しました。
オススメのpandas
本については、次の記事で紹介しています。