Fusionando dataframes de Pandas usando el índice en el estilo de fusión de revisión

Tengo dos dataframes Pandas bastante grandes, como ~ 300k filas, una con N ~ 30 columnas (incluyendo una "Descripción" uno), la otra con una sola columna "Descripción". El primer df contiene datos completos, pero con algunas líneas demasiadas (unos pocos miles) y algunas otras líneas faltantes (unas 600), distribuidas de forma más o less uniforme a lo largo de ella; el otro especifica correctamente las líneas, pero no tiene más datos. Me gustaría combinarlos en un solo dataframe que tenga las líneas especificadas por este último y la información del primero (es decir, descartar filas que no aparecen en este último y crear nuevas filas cuando sea necesario, por ejemplo, rellenar con nan's). Por lo tanto, el dataframe final debe tener un tamaño M x N, donde M es el número de filas del segundo dataframe.

Este sería un caso prototípico para pandas.merge, si no fuera por el hecho de que las keys en las que quiero fusionar tienen duplicates. Son "en su mayoría únicos", pero algunas inputs se repiten (generalmente después de no less de 100 líneas), y no quiero que aparezcan varias veces. En cambio, me gustaría hacer algo que se parezca al "control de versión", es decir, comparar línea por línea para get la mejor coincidencia de las dos descripciones, eliminar las líneas agregadas en el primer dataframe y empujar las nuevas de las correctas. De hecho, si solo extraigo la columna "Descripción" de ambos df en dos CSV, puedo hacer fácilmente lo que necesito a mano, por ejemplo meld (las líneas son lo suficientemente largas como para que no haya ambigüedad en la forma de verificar líneas iguales), pero 1) esto es lento y 2) no resuelve mi problema (al final solo obtendría un duplicado del segundo dataframe, ya que tuve que soltar las otras columnas para usar meld).

Para ejemplificar, diga que tengo los siguientes dos frameworks de datos:

df1 = pd.DataFrame({'Description': ['A','B','Y','D','A','E','F','Y','B'], 'Values': np.arange(9)**2}) df2 = pd.DataFrame({'Description': ['A','B','D','A','E','B','F','B']}) >>> df1 Description Values 0 A 0 1 B 1 2 Y 4 3 D 9 4 A 16 5 E 25 6 F 36 7 Y 49 8 B 64 >>> df2 Description 0 A 1 B 2 D 3 A 4 E 5 B 6 F 7 B 

El que me gustaría get es:

  Description Values 0 A 0.0 1 B 1.0 2 D 9.0 3 A 16.0 4 E 25.0 5 B NaN 6 F 36.0 7 B 64.0 

El único tipo de solución que encontré es agregar una columna al primer dataframe que replica el índice simplemente

 df1['id'] = df1.index 

(que sé que es el estándar, es decir np.arange(len(df1)) ), use pd.merge(df1, df2, how='right') , y luego extraiga de los datos fusionados los índices correspondientes a un aumento máximo secuencia de la columna id. Para esto, ver, por ejemplo, la subsecuencia creciente más larga que necesitaría ser adaptada para include siempre cualquier NaN en la secuencia.

Sin embargo, antes de redevise la rueda, me preguntaba si alguien sabe una implementación ya existente de este código, tal vez en algún package que se use para el control de versiones automatizadas.

EDITAR: en una versión anterior de la pregunta, df2 era df2 = pd.DataFrame({'Description': ['A','B','D','A','E','Z','F','B']}) . Al leer la primera respuesta de @jezrael, me di count de que sugería que las líneas adicionales son "especiales" con la letra Z , pero en la práctica aparecerán en otras partes de los frameworks de datos. Esto hizo que @jezrael propusiera una respuesta muy agradable y elegante, pero desafortunadamente no funciona para mí.

Por otro lado, para una hipótesis ligeramente simplificadora, en la práctica las filas para soltar son bastante especiales, así que las renombré a 'Y' porque podría eliminarlas de antemano e ignorar esta parte de la pregunta – la parte "creciente" es lo que Realmente me importa

Creo que necesitas crear nuevas columnas con diferentes valores donde se duplica por cumcount :

 df1['a'] = df1.groupby('Description').cumcount() df2['a'] = df2.groupby('Description').cumcount() print (df1) Description Values a 0 A 0 0 1 B 1 0 2 C 4 0 3 D 9 0 4 A 16 1 5 E 25 0 6 F 36 0 7 A 49 2 8 B 64 1 print (df2) Description a 0 A 0 1 B 0 2 D 0 3 A 1 4 E 0 5 Z 0 6 F 0 7 B 1 print (pd.merge(df1, df2, how='right', on=['Description','a'])) Description Values a 0 A 0.0 0 1 B 1.0 0 2 D 9.0 0 3 A 16.0 1 4 E 25.0 0 5 F 36.0 0 6 B 64.0 1 7 Z NaN 0 

Si el order es importante, agregue reset_index , sort_values y dure para las columnas drop helper:

 df = pd.merge(df1, df2.reset_index(), how='right', on=['Description','a']) df = df.sort_values('index').drop(['a','index'], axis=1) print (df) Description Values 0 A 0.0 1 B 1.0 2 D 9.0 3 A 16.0 4 E 25.0 7 Z NaN 5 F 36.0 6 B 64.0