2015-09-18 34 views
11

giống như python pandas: how to find rows in one dataframe but not in another? này nhưng với nhiều cộtPandas: Tìm hàng mà không tồn tại trong DataFrame khác theo nhiều cột

Đây là thiết lập:

import pandas as pd 

df = pd.DataFrame(dict(
    col1=[0,1,1,2], 
    col2=['a','b','c','b'], 
    extra_col=['this','is','just','something'] 
)) 

other = pd.DataFrame(dict(
    col1=[1,2], 
    col2=['b','c'] 
)) 

Bây giờ, tôi muốn chọn các hàng từ df không tồn tại ở các hàng khác. Tôi muốn làm sự lựa chọn bởi col1col2

Trong SQL tôi sẽ làm:

select * from df 
where not exists (
    select * from other o 
    where df.col1 = o.col1 and 
    df.col2 = o.col2 
) 

Và trong Pandas tôi có thể làm một cái gì đó như thế này nhưng nó cảm thấy rất xấu xí. Một phần của sự xấu xa có thể tránh được nếu df có id-cột nhưng nó không phải lúc nào cũng có sẵn.

key_col = ['col1','col2'] 
df_with_idx = df.reset_index() 
common = pd.merge(df_with_idx,other,on=key_col)['index'] 
mask = df_with_idx['index'].isin(common) 

desired_result = df_with_idx[~mask].drop('index',axis=1) 

Vì vậy, có thể có một số cách thanh lịch hơn?

Trả lời

14

Kể từ 0.17.0 có một indicator param mới, bạn có thể vượt qua để merge mà sẽ cho bạn biết liệu các hàng chỉ có mặt ở bên trái, bên phải hoặc cả hai:

In [5]: 
merged = df.merge(other, how='left', indicator=True) 
merged 

Out[5]: 
    col1 col2 extra_col  _merge 
0  0 a  this left_only 
1  1 b   is  both 
2  1 c  just left_only 
3  2 b something left_only 

In [6]:  
merged[merged['_merge']=='left_only'] 

Out[6]: 
    col1 col2 extra_col  _merge 
0  0 a  this left_only 
2  1 c  just left_only 
3  2 b something left_only 

Vì vậy, bây giờ bạn có thể lọc df sáp nhập bằng cách chọn chỉ 'left_only' hàng

+1

Cảm ơn bạn đã quay lại điều này. Bạn có thể làm điều này trong một dòng với 'df.merge (khác, how = 'left', indicator = True) .query ('_ merge ==" left_only "')' nhưng không biết nếu đó là tốt hơn. – Pekka

+0

Cá nhân tôi tìm thấy quá nhiều chuỗi vì lợi ích của việc sản xuất một lớp lót có thể làm cho mã khó đọc hơn, có thể có một số cải thiện về tốc độ và bộ nhớ mặc dù – EdChum

+1

@Pekka: + để quay lại gốc ban đầu trong một dòng: 'df .merge (other, how = 'left', indicator = True) .query ('_ merge == "left_only"'). thả (['_ merge'], axis = 1) ' – SpeedCoder5

1

Thú vị

cols = ['col1','col2'] 
#get copies where the indeces are the columns of interest 
df2 = df.set_index(cols) 
other2 = other.set_index(cols) 
#Look for index overlap, ~ 
df[~df2.index.isin(other2.index)] 

Returns:

col1 col2 extra_col 
0  0 a  this 
2  1 c  just 
3  2 b something 

vẻ tao nhã hơn một chút ...

+1

Nếu bạn đặt chỉ số cho những cols bạn có thể sử dụng [ 'difference'] (http://pandas.pydata.org/pandas -docs/stable/generated/pandas.Index.difference.html # pandas.Index.difference) để đạt được kết quả tương tự – EdChum

Các vấn đề liên quan