Las pandas se unen en columnas con diferentes nombres

Tengo dos marcos de datos diferentes en los que quiero realizar algunas operaciones de SQL. Desafortunadamente, como ocurre con los datos con los que trabajo, la ortografía a menudo es diferente.

Vea a continuación un ejemplo de cómo pensé que se vería la syntax donde el ID de usuario pertenece a df1 y el nombre de usuario pertenece a df2. ¿Alguien me ayudó?

# not working - I assume some syntax issue? pd.merge(df1, df2, on = [['userid'=='username', 'column1']], how = 'left') 

Cuando los nombres son diferentes, use los parámetros xxx_on lugar de on= :

 pd.merge(df1, df2, left_on= ['userid', 'column1'], right_on= ['username', 'column1'], how = 'left') 

Un enfoque alternativo es utilizar la join establecer el índice del dataframe de la derecha en las columnas ['username', 'column1'] :

 df1.join(df2.set_index(['username', 'column1']), on=['userid', 'column1'], how='left') 

El resultado de esta join combina las claves coincidentes de las dos columnas de clave con nombre diferente, userid y username , en una sola columna con el nombre de la columna de clave de df1 , userid ; mientras que la salida de la merge mantiene los dos como columnas separadas. Para ilustrar, considere el siguiente ejemplo:

 import numpy as np import pandas as pd df1 = pd.DataFrame({'ID': [1,2,3,4,5,6], 'pID' : [21,22,23,24,25,26], 'Values' : [435,33,45,np.nan,np.nan,12]}) ## ID Values pID ## 0 1 435.0 21 ## 1 2 33.0 22 ## 2 3 45.0 23 ## 3 4 NaN 24 ## 4 5 NaN 25 ## 5 6 12.0 26 df2 = pd.DataFrame({'ID' : [4,4,5], 'pid' : [24,25,25], 'Values' : [544, 545, 676]}) ## ID Values pid ## 0 4 544 24 ## 1 4 545 25 ## 2 5 676 25 pd.merge(df1, df2, how='left', left_on=['ID', 'pID'], right_on=['ID', 'pid'])) ## ID Values_x pID Values_y pid ## 0 1 435.0 21 NaN NaN ## 1 2 33.0 22 NaN NaN ## 2 3 45.0 23 NaN NaN ## 3 4 NaN 24 544.0 24.0 ## 4 5 NaN 25 676.0 25.0 ## 5 6 12.0 26 NaN NaN df1.join(df2.set_index(['ID','pid']), how='left', on=['ID','pID'], lsuffix='_x', rsuffix='_y')) ## ID Values_x pID Values_y ## 0 1 435.0 21 NaN ## 1 2 33.0 22 NaN ## 2 3 45.0 23 NaN ## 3 4 NaN 24 544.0 ## 4 5 NaN 25 676.0 ## 5 6 12.0 26 NaN 

Aquí, también necesitamos especificar lsuffix y rsuffix en la join para distinguir el Value de la columna superpuesta en la salida. Como se puede ver, la salida de la merge contiene la columna pid adicional del DataFrame lado DataFrame , que IMHO no es necesario dado el contexto de la combinación. Tenga en cuenta también que el tipo de dtype para la columna pid ha cambiado a float64 , que resulta de la conversión ascendente debido a los NaN introducidos desde las filas no coincidentes.

Esta salida estética se obtiene a un costo en rendimiento, ya que la llamada a set_index en el lado derecho del DataFrame incurre en algunos gastos generales. Sin embargo, un perfil rápido y sucio muestra que esto no es demasiado horrible, aproximadamente el 30% , lo que puede valer la pena:

 sz = 1000000 # one million rows df1 = pd.DataFrame({'ID': np.arange(sz), 'pID' : np.arange(0,2*sz,2), 'Values' : np.random.random(sz)}) df2 = pd.DataFrame({'ID': np.concatenate([np.arange(sz/2),np.arange(sz/2)]), 'pid' : np.arange(0,2*sz,2), 'Values' : np.random.random(sz)}) %timeit pd.merge(df1, df2, how='left', left_on=['ID', 'pID'], right_on=['ID', 'pid']) ## 818 ms ± 33.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) %timeit df1.join(df2.set_index(['ID','pid']), how='left', on=['ID','pID'], lsuffix='_x', rsuffix='_y') ## 1.04 s ± 18.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)