60

簡単なパンダの質問:

drop_duplicates()重複に関係するすべての行を削除する機能はありますか?

同等の質問は次のとおりです。パンダにはデータフレームのセットの違いがありますか?

例えば:

In [5]: df1 = pd.DataFrame({'col1':[1,2,3], 'col2':[2,3,4]})

In [6]: df2 = pd.DataFrame({'col1':[4,2,5], 'col2':[6,3,5]})

In [7]: df1
Out[7]: 
   col1  col2
0     1     2
1     2     3
2     3     4

In [8]: df2
Out[8]: 
   col1  col2
0     4     6
1     2     3
2     5     5

たぶん、次のようなものdf2.set_diff(df1)がこれを生成します:

   col1  col2
0     4     6
2     5     5

ただし、私の場合、個別のインデックスを持つデータフレームを処理する必要があるため、インデックスに依存したくありません。

ところで、私は当初、現在のdrop_duplicates()方法の拡張について考えていましたが、集合論の性質を使用する 2 番目のアプローチが一般的にはるかに有用であることに気付きました。ただし、どちらのアプローチも現在の問題を解決します。

ありがとう!

4

12 に答える 12

61

少し複雑ですが、インデックスデータを完全に無視したい場合。データフレームの内容を、列を含むタプルのセットに変換します。

ds1 = set(map(tuple, df1.values))
ds2 = set(map(tuple, df2.values))

この手順により、データフレーム内の重複も削除されます (インデックスは無視されます)。

set([(1, 2), (3, 4), (2, 3)])   # ds1

その後、 set メソッドを使用して何かを見つけることができます。たとえば、違いを見つけるには:

ds1.difference(ds2)

与えます: set([(1, 2), (3, 4)])

必要に応じてデータフレームに戻すことができます。セットはデータフレームの構築に使用できないため、セットをリスト 1 に変換する必要があることに注意してください。

pd.DataFrame(list(ds1.difference(ds2)))
于 2013-08-12T10:43:19.257 に答える
33
from pandas import  DataFrame

df1 = DataFrame({'col1':[1,2,3], 'col2':[2,3,4]})
df2 = DataFrame({'col1':[4,2,5], 'col2':[6,3,5]})


print(df2[~df2.isin(df1).all(1)])
print(df2[(df2!=df1)].dropna(how='all'))
print(df2[~(df2==df1)].dropna(how='all'))
于 2014-12-20T10:15:25.163 に答える
3

マージで交差点のインデックスを取得し、それらをドロップします。

>>> df_all = pd.DataFrame(np.arange(8).reshape((4,2)), columns=['A','B']); df_all
   A  B
0  0  1
1  2  3
2  4  5
3  6  7
>>> df_completed = df_all.iloc[::2]; df_completed
   A  B
0  0  1
2  4  5
>>> merged = pd.merge(df_all.reset_index(), df_completed); merged
   index  A  B
0      0  0  1
1      2  4  5
>>> df_pending = df_all.drop(merged['index']); df_pending
   A  B
1  2  3
3  6  7
于 2016-08-20T18:23:06.853 に答える
2

編集: pandas 0.24.0 以降、MultiIndex オブジェクトをデータ フレームから直接作成できるようになりました。これにより、この回答の構文が大幅に簡素化されます。

df1mi = pd.MultiIndex.from_frame(df1)
df2mi = pd.MultiIndex.from_frame(df2)
dfdiff = df2mi.difference(df1mi).to_frame().reset_index(drop=True)

元の回答

Pandas MultiIndex オブジェクトにはメソッドとして実装された高速な設定操作があるため、DataFrame を MultiIndex に変換し、difference()メソッドを使用してから、結果を DataFrame に戻すことができます。このソリューションは、これまでに示したソリューションよりもはるかに高速で (私の簡単なテストでは 100 倍以上)、元のフレームの行インデックスに依存しません。Piotr が彼の回答で述べたように、np.nan != np.nan であるため、これは null 値で失敗します。null 値を持つ df2 の行は、常に差分に表示されます。また、列は両方の DataFrame で同じ順序にする必要があります。

df1mi = pd.MultiIndex.from_arrays(df1.values.transpose(), names=df1.columns)
df2mi = pd.MultiIndex.from_arrays(df2.values.transpose(), names=df2.columns)
dfdiff = df2mi.difference(df1mi).to_frame().reset_index(drop=True)
于 2018-08-06T17:36:42.770 に答える
2

予測:

  1. df1 と df2 には同じ列があります
  2. これは設定操作であるため、重複は無視されます
  3. セットはそれほど大きくないので、メモリについて心配する必要はありません
union = pd.concat([df1,df2])
sym_diff = union[~union.duplicated(keep=False)]
union_of_df1_and_sym_diff = pd.concat([df1, sym_diff])
diff = union_of_df1_and_sym_diff[union_of_df1_and_sym_diff.duplicated()]
于 2017-11-17T23:32:19.273 に答える
1

Pandas 1.1.0 では、一意の行をvalue_counts数えて、数の違いを見つけることができます。

df1 = pd.DataFrame({'col1':[1,2,3], 'col2':[2,3,4]})
df2 = pd.DataFrame({'col1':[4,2,5], 'col2':[6,3,5]})

diff = df2.value_counts().sub(df1.value_counts(), fill_value=0)

結果:

col1  col2
1     2      -1.0
2     3       0.0
3     4      -1.0
4     6       1.0
5     5       1.0
dtype: float64

正の数を取得します。

diff[diff > 0].reset_index(name='counts')


   col1  col2  counts
0     4     6     1.0
1     5     5     1.0
于 2021-09-20T08:47:37.423 に答える