Pythonに3列のデータフレームがあります。
Name1 Name2 Value
Juan Ale 1
Ale Juan 1
name1列とName2列の組み合わせに基づいて重複を排除したいと考えています。
私の例では、両方の行が等しい(ただし順序が異なる)ため、2番目の行を削除し、最初の行のみを保持するため、最終結果は次のようになります。
Name1 Name2 Value
Juan Ale 1
どんなアイデアでも大歓迎です!
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のソートベースのアルゴリズムを使用します。
duplicated
でnp.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
この質問に少し遅れてイムを知っていますが、とにかく私の貢献をしています:)
get_dummies
とadd
を使用して、ハッシュ可能な行を作成する良い方法もできます。
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)