2016-05-19 35 views
5

Nasıl sadece set çıkarma gibi başka bir dataframe bir pandalar dataframe kaldırmak için:başka dataframe bir pandalar dataframe nasıl kaldırılır

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 

Sonra Df1-df2 sonucu bekliyoruz:

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

Nasıl yapmalı?

Teşekkür ederiz.

+0

Olası yinelenen [pandalar için ayar farkı] (http://stackoverflow.com/questions/18180763/set-difference-for-pandas) – AKS

+0

@ 176coding Lütfen cevaplarımızı gerçek veri setlerinize göre zamanlayın. en hızlı/ – knagaev

cevap

9

Çözüm

Kullanım pd.concatdrop_duplicates(keep=False)

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

ardından

pd.concat birini ekleyerek iki DataFrame birlikte s ekler Açıklama

a b 
1 3 4 

gibi görünüyor hemen sonra. Herhangi bir çakışma varsa, drop_duplicates yöntemiyle yakalanacaktır. Ancak, drop_duplicates varsayılan olarak ilk gözlemden ayrılır ve diğer tüm gözlemleri kaldırır. Bu durumda, her çoğaltmanın kaldırılmasını istiyoruz. Bu nedenle, tam olarak bunu yapan keep=False parametresi.

Tekrarlanan özel bir not df2. Yalnızca bir df2 ile df2 numaralı df1 numaralı herhangi bir satırda, bir kopya sayılmayacak ve kalacaktır. Yalnızca bir df2 ile bu çözüm, yalnızca df2df1'un bir alt kümesi olduğunda çalışır. Bununla birlikte, df2'u iki kez kabul edersek, bir kopya olduğu ve daha sonra kaldırılacağı garanti edilir.

+0

thx, çalışır ve 'pd.concat (df1, df2) .drop_duplicates (keep = False)' veya 'df1.append (df2) .drop_duplicates (keep = False)' işlevini kullanabiliriz – 176coding

+0

@ 176coding umarım Bu sorunuza cevap veriyor. Değilse, cevapsız kalmanın ne olduğunu bana bildirin ve bunu çözmek için elimden gelenin en iyisini yapacağım. – piRSquared

+1

@piRSquared Cevabınız doğru değil - simetrik bir fark yarattınız, fark değil (basit). – knagaev

0

Kümeleme mantığı yaklaşımı. df1 ve df2 satırlarını setlere dönüştürün. Ardından yeni 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 
0

bir maskeleme yaklaşımdır sorudan birleştirme df1 ve df2 ile

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

    a b 
1 3 4 
+0

'.tolist()' gerekmez. – Stefan

0

Benim atış tanımlamak için set çıkarma kullanın.

Sen oldukça etkileyici olmanın yararı vardır .duplicated kullanabilirsiniz

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 
+0

Neler olup bittiğine dair bir açıklama, bunu daha zengin bir cevap haline getirecektir. Bu yöntemin başarısının anahtarının 'gösterge' parametresi olduğunu ve true değerine ayarlanmasının, çözümünüzün filtrelenecek son adımda kullandığı her bir satıra konum bilgisi ekleyeceğini ve yalnızca soldaki verilerde görünen satırları tuttuğunu belirttiniz. çerçeve (gösterge == 'left_only'). – Dannid

1

kullanma 'göstergesi' parametresi: Karşılaştırma için

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

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

: Özetle

%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 karşılaştırması en hızlıdır. Orada .tolist()'a gerek yok.