web-dev-qa-db-ja.com

pandasデータフレームを別のデータフレームから削除する方法

セット減算のように、別のデータフレームからpandasデータフレームを削除する方法:

a=[1,2,3,4,5]
b=[1,5]
a-b=[2,3,4]

そして今、2つのpandasデータフレーム、df1からdf2を削除する方法があります:

In [5]: df1=pd.DataFrame([[1,2],[3,4],[5,6]],columns=['a','b'])
In [6]: df1
Out[6]:
   a  b
0  1  2
1  3  4
2  5  6


In [9]: df2=pd.DataFrame([[1,2],[5,6]],columns=['a','b'])
In [10]: df2
Out[10]:
   a  b
0  1  2
1  5  6

Df1-df2の結果は次のようになります。

In [14]: df
Out[14]:
   a  b
0  3  4

どうやってするの?

ありがとうございました。

22
176coding

溶液

_pd.concat_に続いてdrop_duplicates(keep=False)を使用します

_pd.concat([df1, df2, df2]).drop_duplicates(keep=False)
_

のように見える

_   a  b
1  3  4
_

説明

_pd.concat_は、2つのDataFramesを次々に追加して追加します。重複がある場合は、_drop_duplicates_メソッドによってキャプチャされます。ただし、_drop_duplicates_はデフォルトで最初の観測を残し、他のすべての観測を削除します。この場合、すべての重複を削除する必要があります。したがって、まさにそれを行う_keep=False_パラメーター。

繰り返される_df2_に対する特別な注意。 _df2_が1つだけの場合、_df2_にない_df1_の行は重複と見なされずに残ります。 _df2_が1つだけのこのソリューションは、_df2_が_df1_のサブセットである場合にのみ機能します。ただし、_df2_を2回連結すると、重複することが保証され、その後削除されます。

35
piRSquared

_.duplicated_を使用できます。これには、かなり表現力豊かであるという利点があります。

_%%timeit
combined = df1.append(df2)
combined[~combined.index.duplicated(keep=False)]

1000 loops, best of 3: 875 µs per loop
_

比較のために:

_%timeit df1.loc[pd.merge(df1, df2, on=['a','b'], how='left', indicator=True)['_merge'] == 'left_only']

100 loops, best of 3: 4.57 ms per loop


%timeit pd.concat([df1, df2, df2]).drop_duplicates(keep=False)

1000 loops, best of 3: 987 µs per loop


%timeit df2[df2.apply(lambda x: x.value not in df2.values, axis=1)]

1000 loops, best of 3: 546 µs per loop
_

つまり、_np.array_比較を使用するのが最も高速です。 .tolist()は必要ありません。

6
Stefan

セットロジックアプローチ。 df1およびdf2の行をセットに変換します。次に、set減算を使用して、新しいDataFrameを定義します

idx1 = set(df1.set_index(['a', 'b']).index)
idx2 = set(df2.set_index(['a', 'b']).index)

pd.DataFrame(list(idx1 - idx2), columns=df1.columns)

   a  b
0  3  4
2
piRSquared

質問からのdf1とdf2のマージのショット。

「インジケータ」パラメータの使用

In [74]: df1.loc[pd.merge(df1, df2, on=['a','b'], how='left', indicator=True)['_merge'] == 'left_only']
Out[74]: 
   a  b
1  3  4
2
knagaev

マスキングアプローチ

df1[df1.apply(lambda x: x.values.tolist() not in df2.values.tolist(), axis=1)]

   a  b
1  3  4
1
piRSquared

最初のtolist()を削除する必要があると思いますが、2番目の_を保持します。

df1[df1.apply(lambda x: x.values() not in df2.values.tolist(), axis=1)]
0
Peter Abdou

最も簡単なオプションは、インデックスを使用することです。

  1. Df1とdf2を追加し、それらのインデックスをリセットします。

    df = df1.concat(df2)
    df.reset_index(inplace=True)

  2. 例えば:
    これはdf2インデックスを提供します

    indexes_df2 = df.index[ (df["a"].isin(df2["a"]) ) & (df["b"].isin(df2["b"]) ) result_index = df.index[~index_df2] result_data = df.iloc[ result_index,:]

質問は少し前に投稿されましたが、それが新しい読者に役立つことを願っています:)

0
frozen shine