Solo copia una columna clave en el DataFrame fusionado

Considere los siguientes DataFrames:

df1 = pd.DataFrame({'a': [0, 1, 2, 3], 'b': list('abcd')}) df2 = pd.DataFrame({'c': list('abcd'), 'd': 'Alex'}) 

En este caso, df1['b'] y df2['c'] son las columnas clave. Así que cuando se fusiona:

 df1.merge(df2, left_on='b', right_on='c') abcd 0 0 aa Alex 1 1 bb Alex 2 2 cc Alex 3 3 dd Alex 

Termino con ambas columnas clave en el DataFrame resultante cuando solo necesito una. He estado usando:

 df1.merge(df2, left_on='b', right_on='c').drop('c', axis='columns') 

¿Hay una manera de mantener solo una columna clave?

Una forma es establecer b y c como el índice de sus marcos, respectivamente, y usar join seguido de reset_index :

 df1.set_index('b').join(df2.set_index('c')).reset_index() bad 0 a 0 Alex 1 b 1 Alex 2 c 2 Alex 3 d 3 Alex 

Esto será más rápido que el método de merge/drop en grandes marcos de datos, principalmente porque la drop es lenta. El método de @Bill es más rápido que mi sugerencia, y @WB y @PiRsquared superan fácilmente las otras sugerencias:

 import timeit df1 = pd.concat((df1 for _ in range(1000))) df2 = pd.concat((df2 for _ in range(1000))) def index_method(df1 = df1, df2 = df2): return df1.set_index('b').join(df2.set_index('c')).reset_index() def merge_method(df1 = df1, df2=df2): return df1.merge(df2, left_on='b', right_on='c').drop('c', axis='columns') def rename_method(df1 = df1, df2 = df2): return df1.rename({'b': 'c'}, axis=1).merge(df2) def index_method2(df1 = df1, df2 = df2): return df1.join(df2.set_index('c'), on='b') def assign_method(df1 = df1, df2 = df2): return df1.set_index('b').assign(c=df2.set_index('c').d).reset_index() def map_method(df1 = df1, df2 = df2): return df1.assign(d=df1.b.map(dict(df2.values))) >>> timeit.timeit(index_method, number=10) / 10 0.7853091600998596 >>> timeit.timeit(merge_method, number=10) / 10 1.1696729859002517 >>> timeit.timeit(rename_method, number=10) / 10 0.4291436871004407 >>> timeit.timeit(index_method2, number=10) / 10 0.5037374985004135 >>> timeit.timeit(assign_method, number=10) / 10 0.0038641377999738325 >>> timeit.timeit(map_method, number=10) / 10 0.006620216699957382 

Otra forma es darle a b y c el mismo nombre. Al menos para la operación de fusión.

 df1.rename({'b': 'c'}, axis=1).merge(df2) acd 0 0 a Alex 1 1 b Alex 2 2 c Alex 3 3 d Alex 

O use un set_index y left_index=True y right_on patwigter:

 df1.set_index('b').merge(df2, left_index=True, right_on='c') 

Salida:

  acd 0 0 a Alex 1 1 b Alex 2 2 c Alex 3 3 d Alex 

Después de set_index puedes assign directamente el valor

 df1.set_index('b').assign(c=df2.set_index('c').d).reset_index() Out[233]: bac 0 a 0 Alex 1 b 1 Alex 2 c 2 Alex 3 d 3 Alex 

map

Método odioso (no recomendado) que me obligaron a dejar porque publicé accidentalmente una respuesta duplicada a otra persona.

 df1.assign(d=df1.b.map(dict(df2.values))) abd 0 0 a Alex 1 1 b Alex 2 2 c Alex 3 3 d Alex