Python
 Computer >> コンピューター >  >> プログラミング >> Python

【Pandas入門】重複行を検出・抽出・削除する方法を徹底解説

データ分析を行っていると、重複した行をすぐに削除してしまうのではなく、まず中身を確認しながらデータへの理解を深めたい場面があります。

幸い、pandasには重複行を扱うための便利なメソッドがいくつか用意されています。本記事では、公開されているHRデータセットを使用しながら、重複行の検出・抽出・削除の方法を、実際のコードと実行結果とともにわかりやすく解説します。

duplicated() メソッドで重複行を検出する

duplicated() メソッドを使うと、DataFrame内の重複している行を簡単に抽出できます。ここでは重複を含むサンプルとして、GitHub上で公開されているHRデータセットを読み込みます。

import pandas as pd
import numpy as np

# HRデータセットから必要な列のみ読み込む
df = pd.read_csv("https://raw.githubusercontent.com/sasankac/TestDataSet/master/HRDataset.csv",
                 usecols=("Employee_Name", "PerformanceScore", "Position", "CitizenDesc"))

# 従業員名でソートし、元のDataFrameにも反映させる
df.sort_values("Employee_Name", inplace=True)
df.head(3)
Employee_NamePositionCitizenDescPerformanceScore
0AdinolfiProduction Technician IUS CitizenExceeds
1AdinolfiSr. DBAUS CitizenFully Meets
2AdinolfiProduction Technician IIUS CitizenFully Meets

keep引数のデフォルト動作

duplicated() の挙動は、デフォルトでは keep 引数によって決まります。keep 引数は、各値の最初の出現行を非重複としてマークします。

ポイントは、「同じ値が複数回現れたらすべて重複」と判断されるわけではないことです。あくまで最初の行以降に出てくる行が重複として判定されます。

イメージとしては次のとおりです。かごの中に3個のリンゴがある場合、最初のリンゴを「非重複」、残りの2個を「重複」としてマークします。

実行例

df["Employee_Name"].head(3)

出力

0    Adinolfi
1    Adinolfi
2    Adinolfi
Name: Employee_Name, dtype: object

実行例

df["Employee_Name"].duplicated().head(3)

出力

0    False
1     True
2     True
Name: Employee_Name, dtype: bool

実際に重複行を取り出すには、この結果をブールインデックスとしてDataFrameに渡します(最初の出現行は重複ではなく、2回目以降の出現行が出力されます)。

df.shape
(310, 4)
df[df["Employee_Name"].duplicated()]
Employee_NamePositionCitizenDescPerformanceScore
1AdinolfiSr. DBAUS CitizenFully Meets
2AdinolfiProduction Technician IIUS CitizenFully Meets
6AndersonProduction Technician IUS CitizenExceeds
...............
307WangData AnalystUS CitizenFully Meets

全310行のうち、.duplicated() メソッドによって79行が重複として抽出されました。

keep="last" を指定する

デフォルトでは最初の出現行が非重複として扱われますが、keep = "last" を渡すことでこの挙動を変更できます。

この設定では、先ほどのリンゴの例でいうと、最初の2個を重複、最後の1個を非重複としてマークします。

df[df["Employee_Name"].duplicated(keep="last")]
Employee_NamePositionCitizenDescPerformanceScore
0AdinolfiProduction Technician IUS CitizenExceeds
1AdinolfiSr. DBAUS CitizenFully Meets
5AndersonProduction Technician IUS CitizenFully Meets
...............
306WangCIOUS CitizenExceeds

keep=False を指定する

keep 引数には False も指定できます。この場合は、複数回出現する値をすべて重複としてマークします。リンゴの例では、最初でも最後でもなく、3個すべてが重複とみなされます。

注意:False を指定するときはクォーテーションを付けないようにしてください(文字列ではなくPythonの真偽値として渡します)。

df[df["Employee_Name"].duplicated(keep=False)]
Employee_NamePositionCitizenDescPerformanceScore
0AdinolfiProduction Technician IUS CitizenExceeds
1AdinolfiSr. DBAUS CitizenFully Meets
4AdinolfiProduction ManagerUS CitizenFully Meets
...............
307WangData AnalystUS CitizenFully Meets

チルダ(〜)でユニークな値だけを抽出する

最後に、否定演算子 ~(チルダ)を使えば、重複を示す真偽値を反転させ、重複していない行=ユニークな行だけを取り出せます。

df_unique = df[~df["Employee_Name"].duplicated(keep=False)]
df_unique
Employee_NamePositionCitizenDescPerformanceScore
7AndreolaSoftware EngineerUS CitizenFully Meets
25BozziProduction ManagerUS CitizenFully Meets
26BramanteDirector of OperationsUS CitizenExceeds
...............
308ZhouProduction Technician IUS CitizenFully Meets
309ZimaNaNNaNNaN

drop_duplicates() メソッドで重複行を削除する

drop_duplicates() は前述の duplicated() とよく似たメソッドですが、Series単体ではなくDataFrameに対して直接使用できる点が特徴です。

注意:このメソッドはDataFrameの全列を対象に重複行を判定し、重複している行を削除します。

len(df)

出力

310
len(df.drop_duplicates())

出力

290

subset引数で判定対象の列を絞る

subset 引数には、文字列のリストとして列名を渡せます。これにより、指定した列だけを基準に重複をチェックできます。

df1 = df.drop_duplicates(subset=["Employee_Name"], keep="first")
df1
Employee_NamePositionCitizenDescPerformanceScore
0AdinolfiProduction Technician IUS CitizenExceeds
5AndersonProduction Technician IUS CitizenFully Meets
7AndreolaSoftware EngineerUS CitizenFully Meets
...............
308ZhouProduction Technician IUS CitizenFully Meets
309ZimaNaNNaNNaN

さらに、複数の列を指定することもでき、前のセクションで説明したすべての keep 引数も組み合わせて使えます。

df1 = df.drop_duplicates(subset=["Employee_Name", "CitizenDesc"], keep=False)
df1
Employee_NamePositionCitizenDescPerformanceScore
7AndreolaSoftware EngineerUS CitizenFully Meets
16BeakProduction Technician IEligible NonCitizenFully Meets
25BozziProduction ManagerUS CitizenFully Meets
...............
308ZhouProduction Technician IUS CitizenFully Meets
309ZimaNaNNaNNaN

unique() メソッドでユニーク値を配列として取得する

unique() メソッドは、Series内の一意な値を検索し、NumPy配列として返します。このメソッドは欠損値を除外しない点にも注意してください。

len(df["Employee_Name"])

出力

310
df["Employee_Name"].unique()

出力(抜粋)

array(['Adinolfi', 'Anderson', 'Andreola', 'Athwal', 'Beak', 'Bondwell',
       'Bozzi', 'Bramante', 'Brill', 'Brown', ... ,
       'Von Massenbach', 'Wallace', 'Wang', 'Zhou', 'Zima'], dtype=object)
len(df["Employee_Name"].unique())

出力

231

nunique() メソッドでユニーク値の個数を取得する

nunique() メソッドは、Series内の一意な値の個数を返します。デフォルトでは dropna = True が設定されており、欠損値はカウントから除外されます。

欠損値も含めてカウントしたい場合は、dropna 引数に False を渡してください。

df["Employee_Name"].nunique()

出力

231
df["Employee_Name"].nunique(dropna=False)

出力

231

まとめ

pandasでの重複データ処理には、主に以下のメソッドを使い分けます。

  • duplicated():重複行を真偽値で検出する。keep引数(first / last / False)で判定基準を変更可能。
  • drop_duplicates():重複行を直接削除する。subset引数で判定対象の列を指定できる。
  • unique():Seriesのユニーク値を配列として取得する(欠損値を含む)。
  • nunique():ユニーク値の個数を取得する(デフォルトで欠損値を除外)。

これらのメソッドを組み合わせれば、重複の確認から除去、ユニーク値の集計まで柔軟に行えます。データクレンジングの品質向上にぜひ活用してください。

  1. Windows 10で重複した写真を見つけて削除する方法【無料ツール活用術】

    デジタル画像の悩みのひとつが、不要なストレージ容量を占有してしまう「重複写真」です。PCの保存容量には限りがあるため、多くのユーザーはさまざまな方法でファイル整理を模索しています。容量を確保する最も効果的な手段のひとつが、必要のない重複画像を削除し、ユニークな画像だけを残すことです。本記事では、Windows 10向けの優れた重複写真検出ツールを使って、重複写真を見つけて削除する方法を詳しく解説します。 重複写真が発生する原因 重複を削除すべき理由 同じファイルのバックアップを作成した 複数のユーザーとファイルを共有・受信した インターネットから同じファイルをダウンロード

  2. PCで回転・反転された重複画像を見つける方法

    スマートフォンは今や子どもから大人、年配の方々まで幅広い層に普及しています。スマホで写真を撮る人もますます増えており、どこへ行っても人生の素晴らしい瞬間を記録できるようになりました。撮影した写真はその場で家族や友人、大切な人に送れるため、まるでその場に一緒にいるかのような感覚を共有することができます。 しかし、数年かけて集めた何千枚、何万枚もの画像が蓄積されると、写真コレクションの整理が非常に大変になることをご存じでしょうか。重複画像は、それまで見栄えの良かったコレクションを台無しにしてしまいます。大切な思い出を探したいときに、目的の写真が見つけにくくなる原因にもなります。反転・回転・色調変