¿Cómo restar filas de un dataframe pandas de otro?

La operación que quiero hacer es similar a la fusión. Por ejemplo, con la fusión inner obtenemos un dataframe que contiene filas que están presentes en el primer y segundo dataframe. Con la fusión outer obtenemos un dataframe que está presente O BIEN en el primer O en el segundo dataframe.

Lo que necesito es un dataframe que contenga filas que estén presentes en el primer dataframe Y QUE NO estén presentes en el segundo. ¿Hay una manera rápida y elegante de hacerlo?

¿Qué tal algo como lo siguiente?

 print df1 Team Year foo 0 Hawks 2001 5 1 Hawks 2004 4 2 Nets 1987 3 3 Nets 1988 6 4 Nets 2001 8 5 Nets 2000 10 6 Heat 2004 6 7 Pacers 2003 12 print df2 Team Year foo 0 Pacers 2003 12 1 Heat 2004 6 2 Nets 1988 6 

Siempre que haya una columna con el nombre no clave, puede dejar que los sufijos agregados hagan el trabajo (si no hay una columna común sin clave, puede crear una para usar temporalmente … df1['common'] = 1 y df2['common'] = 1 ):

 new = df1.merge(df2,on=['Team','Year'],how='left') print new[new.foo_y.isnull()] Team Year foo_x foo_y 0 Hawks 2001 5 NaN 1 Hawks 2004 4 NaN 2 Nets 1987 3 NaN 4 Nets 2001 8 NaN 5 Nets 2000 10 NaN 

O puedes usar isin pero deberías crear una sola clave:

 df1['key'] = df1['Team'] + df1['Year'].astype(str) df2['key'] = df1['Team'] + df2['Year'].astype(str) print df1[~df1.key.isin(df2.key)] Team Year foo key 0 Hawks 2001 5 Hawks2001 2 Nets 1987 3 Nets1987 4 Nets 2001 8 Nets2001 5 Nets 2000 10 Nets2000 6 Heat 2004 6 Heat2004 7 Pacers 2003 12 Pacers2003 

Considera lo siguiente:

  1. df_one es el primer DataFrame
  2. df_two es el segundo DataFrame

Presente en el primer dataframe y no en el segundo dataframe

Solución: por el índice df = df_one[~df_one.index.isin(df_two.index)]

El índice puede ser reemplazado por la columna requerida en la que desea hacer la exclusión. En el ejemplo anterior, he usado el índice como referencia entre ambas ttwigs de datos

Además, también puede usar una consulta más compleja usando pandas.Series booleanas para resolver lo anterior.

Podría tener errores si su columna no indexada tiene celdas con NaN.

 print df1 Team Year foo 0 Hawks 2001 5 1 Hawks 2004 4 2 Nets 1987 3 3 Nets 1988 6 4 Nets 2001 8 5 Nets 2000 10 6 Heat 2004 6 7 Pacers 2003 12 8 Problem 2112 NaN print df2 Team Year foo 0 Pacers 2003 12 1 Heat 2004 6 2 Nets 1988 6 3 Problem 2112 NaN new = df1.merge(df2,on=['Team','Year'],how='left') print new[new.foo_y.isnull()] Team Year foo_x foo_y 0 Hawks 2001 5 NaN 1 Hawks 2004 4 NaN 2 Nets 1987 3 NaN 4 Nets 2001 8 NaN 5 Nets 2000 10 NaN 6 Problem 2112 NaN NaN 

El equipo problemático en 2112 no tiene valor para foo en ninguna de las tablas. Por lo tanto, la unión izquierda aquí devolverá falsamente esa fila, que coincide en ambos DataFrames, ya que no está presente en el DataFrame derecho.

Solución:

Lo que hago es agregar una columna única al DataFrame interno y establecer un valor para todas las filas. Luego, cuando se une, puede verificar si esa columna es NaN para que la tabla interna encuentre registros únicos en la tabla externa.

 df2['in_df2']='yes' print df2 Team Year foo in_df2 0 Pacers 2003 12 yes 1 Heat 2004 6 yes 2 Nets 1988 6 yes 3 Problem 2112 NaN yes new = df1.merge(df2,on=['Team','Year'],how='left') print new[new.in_df2.isnull()] Team Year foo_x foo_y in_df1 in_df2 0 Hawks 2001 5 NaN yes NaN 1 Hawks 2004 4 NaN yes NaN 2 Nets 1987 3 NaN yes NaN 4 Nets 2001 8 NaN yes NaN 5 Nets 2000 10 NaN yes NaN 

NÓTESE BIEN. La fila problemática ahora se filtra correctamente, porque tiene un valor para in_df2.

  Problem 2112 NaN NaN yes yes 

Sugiero usar el parámetro ‘indicador’ en la combinación. Además, si ‘on’ es None, este valor predeterminado es la intersección de las columnas en ambos DataFrames.

 new = df1.merge(df2,how='left', indicator=True) # adds a new column '_merge' new = new[(new['_merge']=='left_only')].copy() #rows only in df1 and not df2 new = new.drop(columns='_merge').copy() Team Year foo 0 Hawks 2001 5 1 Hawks 2004 4 2 Nets 1987 3 4 Nets 2001 8 5 Nets 2000 10 

Referencia: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.merge.html

 indicator : boolean or string, default False If True, adds a column to output DataFrame called “_merge” with information on the source of each row. Information column is Categorical-type and takes on a value of “left_only” for observations whose merge key only appears in 'left' DataFrame, “right_only” for observations whose merge key only appears in 'right' DataFrame, and “both” if the observation's merge key is found in both.