パンダの重複データの削除


重複するデータで終わるために時系列データを扱うとき、それは非常に一般的でありえます.これは様々な理由で起こることができます、そして、私は1回以上遭遇しました、そして、重複した価値を除くために異なるアプローチを試みました.があるgem of a solution on Stack Overflow そして、私はこの問題への可能な解決策を歩くことが役に立つと思いました.
物事を簡単に保つために、私はただで働くSeries 浮動小数点数データ.これは何でもあるかもしれませんが、私たちは、在庫のための収益見積もり、または温度読書、または特定の日付の店の販売のように手動で維持されている何かを偽造することができます.
>>> import pandas as pd
>>> import numpy as np
>>>
>>> items = pd.Series(np.random.random_sample(10) * 100, pd.date_range('2020-01-01', periods=10))
>>>
>>> items
2020-01-01 65.685092
2020-01-02 15.376536
2020-01-03 89.002061
2020-01-04 38.614841
2020-01-05 39.274465
2020-01-06 6.886290
2020-01-07 96.453986
2020-01-08 56.488125
2020-01-09 61.667168
2020-01-10 18.023665
Freq: D, dtype: float64
この時点で、私たちはデータの10の期間とインデックスDatetimeIndex 10日ですべてのユニークな値があります.しかし、我々のデータで言うように、訂正されたデータは同じソースファイルに現れます.私はここで少し工夫されて、2を連結する何かをしますSeries それはそれらに同じ日付のいくつかを持っていますが、実際の生活では、データが同じタイムスタンプの重複データを使用してソースに表示される方法の数を想像することができます.
>>> corrected = pd.Series(np.random.random_sample(3) * 75, pd.date_range('2020-01-04', periods=3))
>>> combined = pd.concat([items, corrected])
さて、どうやってこの複製データを取り除くのですか?我々が我々が使用するのを好む修正か更新された値であると仮定して、我々が我々のファイルで最新のデータをただ保つだけであると言いましょう.スタックオーバーフローで受け入れられている解決策の右側に行く代わりに、可能な解決策が何であるかを見るために、Pandasドキュメンテーションを通して働くつもりです、そして、うまくいけば、同じ場所で終わります!
まず最初に、我々のデータがインデックスで項目を複製しているかどうかの質問に答えることができるかどうか見てみましょう.パンダのドキュメントでは、いくつかの有望な方法を見ます duplicated 方法、およびhas_duplicates プロパティ.これらのレポートが我々が予想するかどうか見ましょう.
>>> combined.index.has_duplicates
True
現在、見ることができるメソッドはそうですduplicated and drop_duplicates . For duplicated , このメソッドはブール値の配列を返しますTrue 複製を示す.あなたはkeep あなたのインデックスの値の最初の(デフォルト)か最後の出来事を保つ引数.インdrop_duplicates , あなたは得るIndex 既に削除された重複で返され、keep 同じ意味の引数.
>>> combined.index.duplicated(keep='last')
array([False, False, False, True, True, True, False, False, False,
       False, False, False, False])
>>> combined.index.drop_duplicates(keep='last')
DatetimeIndex(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-07',
               '2020-01-08', '2020-01-09', '2020-01-10', '2020-01-04',
               '2020-01-05', '2020-01-06'],
              dtype='datetime64[ns]', freq=None)
ので、私たちはこれらの2つのオプションを今何を行うのですか?最初のBoolean配列を使用して、我々が保持したい値を選ぶことができますTrue 値は私たちがドロップしたいものです.それは非常に簡単ですが、ちょうど~ . これは、配列から必要な値を選択するために使用することができますし、良い解決策を私たちを取得します.それが年代順でないので、我々はインデックスを分類する必要があります.
>>> ~combined.index.duplicated(keep='last')
array([ True, True, True, False, False, False, True, True, True,
        True, True, True, True])
>>> combined[~combined.index.duplicated(keep='last')].sort_index()
2020-01-01 65.685092
2020-01-02 15.376536
2020-01-03 89.002061
2020-01-04 28.990089
2020-01-05 22.371910
2020-01-06 21.548301
2020-01-07 96.453986
2020-01-08 56.488125
2020-01-09 61.667168
2020-01-10 18.023665
dtype: float64
さて、2番目のメソッドを使いたいなら、drop_duplicates , 我々は、我々の価値をつかむためにそれを使う方法を見つける必要がありますSeries それは、我々が保ちたいです.これは少し複雑です.最初に、我々はreset_index インデックスを取る便利な方法ですDatetimeIndex ) そして、それをAのコラムに変えてくださいDataFrame 新しい規則的な、非繰り返しインデックスで瞬間的に.今、あなたはそれを見ることができますSeries ルックスは少し異なるが、新しい列をすぐに重複を削除するために使用することができます.
>>> combined.reset_index()
        index 0
0 2020-01-01 65.685092
1 2020-01-02 15.376536
2 2020-01-03 89.002061
3 2020-01-04 38.614841
4 2020-01-05 39.274465
5 2020-01-06 6.886290
6 2020-01-07 96.453986
7 2020-01-08 56.488125
8 2020-01-09 61.667168
9 2020-01-10 18.023665
10 2020-01-04 28.990089
11 2020-01-05 22.371910
12 2020-01-06 21.548301
今、我々は使用することができますdrop_duplicates , しかし、我々はDataFrame を持つメソッドのバージョンsubset あるカラム(私たちの新しい「インデックス」列)を考慮するだけで、引数を複製するのに使用できる引数.現在、これは現在DataFrame ではなくSeries , インデックスをインデックスにリセットしますset_index を返します.0 . これは、以前の方法と同じ結果を与えますが、より丸いやり方でも同じです.私も、それがずっとより混乱するとわかります.
>>> combined.reset_index().drop_duplicates(subset='index', keep='last').set_index('index')[0].sort_index()
index
2020-01-01 65.685092
2020-01-02 15.376536
2020-01-03 89.002061
2020-01-04 28.990089
2020-01-05 22.371910
2020-01-06 21.548301
2020-01-07 96.453986
2020-01-08 56.488125
2020-01-09 61.667168
2020-01-10 18.023665
Name: 0, dtype: float64
これを行うもう一つの方法はgroupby とグループ化関数last ) 必要な値を選択します.このメソッドはソート出力を提供し、シンプルに見えます.
>>> combined.groupby(combined.index).last()
2020-01-01 65.685092
2020-01-02 15.376536
2020-01-03 89.002061
2020-01-04 28.990089
2020-01-05 22.371910
2020-01-06 21.548301
2020-01-07 96.453986
2020-01-08 56.488125
2020-01-09 61.667168
2020-01-10 18.023665
dtype: float64
何が最善の方法これを行うには?スタックオーバーフローの問題と同様に、読みやすさのための最初の方法を好みますが、最後はとても簡単です.第1の方法を選ぶための1つの良い議論は速度です.
%timeit combined[~combined.index.duplicated(keep='last')].sort_index()
282 µs ± 15.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit combined.reset_index().drop_duplicates(subset='index', keep='last').set_index('index')[0].sort_index()
1.56 ms ± 28.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit combined.groupby(combined.index).last()
578 µs ± 5.21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
さて、すべてを通して掘り出した後に、私はあなたがAから複製アイテムを取り除く方法についてもう少し理解していることを望みますSeries or DataFrame そして、なぜいくつかの方法が他よりも優れているかもしれません.