web-dev-qa-db-ja.com

Python-2つの列の組み合わせに基づいてデータフレーム内の重複を削除しますか?

Pythonに3列のデータフレームがあります。

Name1 Name2 Value
Juan  Ale   1
Ale   Juan  1

name1列とName2列の組み合わせに基づいて重複を排除したいと考えています。

私の例では、両方の行が等しい(ただし順序が異なる)ため、2番目の行を削除し、最初の行のみを保持するため、最終結果は次のようになります。

Name1 Name2 Value
Juan  Ale   1

どんなアイデアでも大歓迎です!

16
Juan

frozensetに変換して pd.DataFrame.duplicated

res = df[~df[['Name1', 'Name2']].apply(frozenset, axis=1).duplicated()]

print(res)

  Name1 Name2  Value
0  Juan   Ale      1

frozensetは重複をチェックするためにハッシュを使用するため、setの代わりにduplicatedが必要です。

行よりも列のほうが優れています。行数が多い場合は、@ Wenのソートベースのアルゴリズムを使用します。

18
jpp

duplicatednp.sortを使用することにより

df[pd.DataFrame(np.sort(df[['Name1','Name2']].values,1)).duplicated()]
Out[614]: 
  Name1 Name2  Value
1   Ale  Juan      1

性能

df=pd.concat([df]*100000)

%timeit df[pd.DataFrame(np.sort(df[['Name1','Name2']].values,1)).duplicated()]
10 loops, best of 3: 69.3 ms per loop
%timeit df[~df[['Name1', 'Name2']].apply(frozenset, axis=1).duplicated()]
1 loop, best of 3: 3.72 s per loop
21
WeNYoBen

この質問に少し遅れてイムを知っていますが、とにかく私の貢献をしています:)

get_dummiesaddを使用して、ハッシュ可能な行を作成する良い方法もできます。

df[~(pd.get_dummies(df.a).add(pd.get_dummies(df.b), fill_value=0)).duplicated()]

時間は@Wenの答えほど良くはありませんが、apply + frozen_setよりもずっと高速です

df=pd.concat([df]*1000000)
%timeit df[~(pd.get_dummies(df.a).add(pd.get_dummies(df.b), fill_value=0)).duplicated()]
1.8 s ± 85 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit df[pd.DataFrame(np.sort(df[['a','b']].values,1)).duplicated()]
1.26 s ± 19 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit df[~df[['a', 'b']].apply(frozenset, axis=1).duplicated()]
1min 9s ± 684 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
5
rafaelc