pandas.DataFrame, Seriesの重複した行を抽出・削除

pandas.DataFrame, pandas.Seriesから重複した要素を含む行を抽出するにはduplicated()、削除するにはdrop_duplicates()を使います。

pandas.DataFrame.duplicated — pandas 0.22.0 documentation pandas.DataFrame.drop_duplicates — pandas 0.22.0 documentation

また、重複した行の要素を集約するgroupby()についても触れる。 例として以下のデータを使用します。重複したデータを追加しています。

import pandas as pd

df = pd.read_csv('data/src/sample_pandas_normal.csv')
print(df)
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

df = df.append({'name': 'Dave', 'age': 68, 'state': 'TX', 'point': 70}, ignore_index=True)
print(df)
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57
# 6     Dave   68    TX     70

サンプルのcsvファイルはコチラ。

sample_pandas_normal.csv

例はpandas.DataFrameだが、pandas.Seriesでも同様。 以下の内容について説明します。

重複した行を抽出: duplicated() 残す行を選択: 引数keep 重複を判定する列を指定: 引数subset 重複した行の数をカウント

重複した行を削除: drop_duplicates() 引数keep, subset 引数inplace

重複した行を集約: groupby()

重複した行を抽出: duplicated()

duplicated()メソッドを使うと、重複した行をTrueとしたブール値のpandas.Seriesが得られる。デフォルトでは、すべての列の要素が一致しているときに重複したとみなされる。

print(df.duplicated())
# 0    False
# 1    False
# 2    False
# 3    False
# 4    False
# 5    False
# 6     True
# dtype: bool

得られたpandas.Seriesを使って、元のpandas.DataFrameから重複した行のデータを抽出できます。

print(df[df.duplicated()])
#    name  age state  point
# 6  Dave   68    TX     70

残す行を選択: 引数keep

デフォルトでは引数keep='first'となっており、重複した最初の行はFalseになる。最初(first)の行が重複とみなされずkeepされるイメージ。 keep='last'とすると、重複した最後の行はFalseになる。最後(last)の行が重複とみなされずkeepされるイメージ。

print(df.duplicated(keep='last'))
# 0    False
# 1    False
# 2    False
# 3     True
# 4    False
# 5    False
# 6    False
# dtype: bool

keep=Falseとすると、重複した行すべてがTrueとなります。

print(df.duplicated(keep=False))
# 0    False
# 1    False
# 2    False
# 3     True
# 4    False
# 5    False
# 6     True
# dtype: bool

重複を判定する列を指定: 引数subset

上述のように、デフォルトではすべての列の要素が一致しているときに重複したとみなされる。 引数subsetで判定する列を指定することができます。

print(df.duplicated(subset='state'))
# 0    False
# 1    False
# 2     True
# 3    False
# 4     True
# 5     True
# 6     True
# dtype: bool

リストで複数の列を指定することも可能。指定したすべての列の要素が一致しているときに重複したとみなされる。

print(df.duplicated(subset=['state', 'point']))
# 0    False
# 1    False
# 2    False
# 3    False
# 4    False
# 5    False
# 6     True
# dtype: bool

重複した行の数をカウント

value_counts()を使ってduplicated()で得られたpandas.SeriesのTrueをカウントすると、重複した行の数が確認できます。 value_counts()については以下の記事参照。

引数keepによって結果が変わるので注意。目的によって使い分ける。

print(df.duplicated().value_counts())
# False    6
# True     1
# dtype: int64

print(df.duplicated().value_counts()[True])
# 1

print(df.duplicated(keep=False).value_counts()[True])
# 2

重複した行を削除: drop_duplicates()

duplicated()と論理否定演算子~を使って、重複した行を削除したDataFrameを取得できます。

print(df[~df.duplicated()])
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

同様の処理を行うdrop_duplicates()メソッドが用意されています。

print(df.drop_duplicates())
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

引数keep, subset

drop_duplicates()でも、duplicated()と同様に引数keep, subsetを設定できます。

print(df.drop_duplicates(keep=False))
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

print(df.drop_duplicates(subset='state'))
#     name  age state  point
# 0  Alice   24    NY     64
# 1    Bob   42    CA     92
# 3   Dave   68    TX     70

引数inplace

デフォルトでは重複した行が削除された新たなDataFrameが返されるが、引数inplace=Trueとすると、元のDataFrameから重複した行が削除される。

df.drop_duplicates(subset='state', keep='last', inplace=True)
print(df)
#     name  age state  point
# 4  Ellen   24    CA     88
# 5  Frank   30    NY     57
# 6   Dave   68    TX     70

重複した行を集約: groupby()

重複した要素がある列を基準に値を集約するにはgroupby()を使います。 平均や合計、最大、最小などのメソッドが用意されています。平均(mean())は数値列にのみ適用される。

df = pd.read_csv('data/src/sample_pandas_normal.csv')
print(df)
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

print(df.groupby('state').mean())
#         age      point
# state                 
# CA     28.0  83.333333
# NY     27.0  60.500000
# TX     68.0  70.000000

文字列を連結したりリスト化したりすることも可能。

print(df.groupby('state').agg(
    {'name': lambda x: ','.join(x),
     'age': 'mean',
     'point': 'mean'}))
#                     name  age      point
# state                                   
# CA     Bob,Charlie,Ellen   28  83.333333
# NY           Alice,Frank   27  60.500000
# TX                  Dave   68  70.000000

print(df.groupby('state').agg(
    {'name': list,
     'age': 'mean',
     'point': 'mean'}))
#                         name  age      point
# state                                       
# CA     [Bob, Charlie, Ellen]   28  83.333333
# NY            [Alice, Frank]   27  60.500000
# TX                    [Dave]   68  70.000000

groupby()の詳細は以下の記事を参照。

連結には無名関数(ラムダ式)で文字列のメソッドjoin()を適用しています。

リスト化は組み込み関数list()を適用。リストをpandas.DataFrameの要素とした場合の処理については以下の記事を参照。

シェア

関連カテゴリー

Python pandas

pandasのオプション設定を確認・変更する方法 pandasの時系列データにおける頻度(引数freq)の指定方法 pandas.DataFrame, Seriesをソートするsort_values, sort_index pandas, Matplotlib(mpl_finance)でローソク足チャートを作成 pandasでstack, unstack, pivotを使ってデータを整形 pandasのjson_normalizeで辞書のリストをDataFrameに変換 pandasで任意の位置の値を取得・変更するat, iat, loc, iloc pandas.DataFrameの行番号、列番号を取得 pandasで欠損値NaNが含まれているか判定、個数をカウント pandas.DataFrame, SeriesとPython標準のリストを相互に変換 pandasで窓関数を適用するrollingを使って移動平均などを算出 pandasのdescribeで各列の要約統計量(平均、標準偏差など)を取得 pandas.DataFrameをGroupByでグルーピングし統計量を算出 pandas.DataFrameに列や行を追加(assign, appendなど)

Last Updated: 6/26/2019, 10:34:03 PM