Eliminar un dataframe de otro con Pandas

Tengo dos marcos de datos de diferente tamaño ( df1 nad df2 ). Me gustaría eliminar de df1 todas las filas que están almacenadas dentro de df2 .

Así que si tengo df2 es igual a:

  AB 0 wer 6 1 tyu 7 

Y df1 es igual a:

  ABC 0 qwe 5 a 1 wer 6 s 2 wer 6 d 3 rty 9 f 4 tyu 7 g 5 tyu 7 h 6 tyu 7 j 7 iop 1 k 

El resultado final debería ser así:

  ABC 0 qwe 5 a 1 rty 9 f 2 iop 1 k 

Pude lograr mi objective utilizando un bucle for, pero me gustaría saber si existe una forma mejor, más elegante y eficiente de realizar dicha operación.

Aquí está el código que escribí en caso de que lo necesite: importar pandas como pd

 df1 = pd.DataFrame({'A' : ['qwe', 'wer', 'wer', 'rty', 'tyu', 'tyu', 'tyu', 'iop'], 'B' : [ 5, 6, 6, 9, 7, 7, 7, 1], 'C' : ['a' , 's', 'd', 'f', 'g', 'h', 'j', 'k']}) df2 = pd.DataFrame({'A' : ['wer', 'tyu'], 'B' : [ 6, 7]}) for i, row in df2.iterrows(): df1 = df1[(df1['A']!=row['A']) & (df1['B']!=row['B'])].reset_index(drop=True) 

Utilice la merge con la merge externa con filtro por query , la última eliminación de la columna auxiliar por drop :

 df = pd.merge(df1, df2, on=['A','B'], how='outer', indicator=True) .query("_merge != 'both'") .drop('_merge', axis=1) .reset_index(drop=True) print (df) ABC 0 qwe 5 a 1 rty 9 f 2 iop 1 k 

Puede usar np.in1d ​​para verificar si existe alguna fila en df1 en df2. Y luego utilícelo como una máscara invertida para seleccionar filas de df1.

 df1[~df1[['A','B']].apply(lambda x: np.in1d(x,df2).all(),axis=1)]\ .reset_index(drop=True) Out[115]: ABC 0 qwe 5 a 1 rty 9 f 2 iop 1 k 

pandas tiene un método llamado isin , sin embargo, esto se basa en índices únicos. Podemos definir una función lambda para crear columnas que podamos usar en esto desde las 'A' y 'B' de df1 y df2 . Luego negamos esto (ya que queremos los valores que no están en df2 ) y restablecemos el índice:

 import pandas as pd df1 = pd.DataFrame({'A' : ['qwe', 'wer', 'wer', 'rty', 'tyu', 'tyu', 'tyu', 'iop'], 'B' : [ 5, 6, 6, 9, 7, 7, 7, 1], 'C' : ['a' , 's', 'd', 'f', 'g', 'h', 'j', 'k']}) df2 = pd.DataFrame({'A' : ['wer', 'tyu'], 'B' : [ 6, 7]}) unique_ind = lambda df: df['A'].astype(str) + '_' + df['B'].astype(str) print df1[~unique_ind(df1).isin(unique_ind(df2))].reset_index(drop=True) 

impresión:

  ABC 0 qwe 5 a 1 rty 9 f 2 iop 1 k 

La forma más limpia que encontré fue usar Drop from pandas usando el índice del dataframe que desea eliminar:

 df1.drop(df2.index, axis=0,inplace=True)