unirse o fusionarse con sobrescribir en pandas

4 minutos de lectura

avatar de usuario de saroele
saroele

Quiero realizar una operación de unir/combinar/agregar en un marco de datos con índice de fecha y hora.

digamos que tengo df1 y quiero agregar df2 lo. df2 puede tener menos o más columnas e índices superpuestos. Para todas las filas donde los índices coinciden, si df2 tiene la misma columna que df1quiero los valores de df1 se sobrescribirá con los de df2.

¿Cómo puedo obtener el resultado deseado?

Avatar de usuario de Wes McKinney
wes mckinney

Qué tal si: df2.combine_first(df1)?

In [33]: df2
Out[33]: 
                   A         B         C         D
2000-01-03  0.638998  1.277361  0.193649  0.345063
2000-01-04 -0.816756 -1.711666 -1.155077 -0.678726
2000-01-05  0.435507 -0.025162 -1.112890  0.324111
2000-01-06 -0.210756 -1.027164  0.036664  0.884715
2000-01-07 -0.821631 -0.700394 -0.706505  1.193341
2000-01-10  1.015447 -0.909930  0.027548  0.258471
2000-01-11 -0.497239 -0.979071 -0.461560  0.447598

In [34]: df1
Out[34]: 
                   A         B         C
2000-01-03  2.288863  0.188175 -0.040928
2000-01-04  0.159107 -0.666861 -0.551628
2000-01-05 -0.356838 -0.231036 -1.211446
2000-01-06 -0.866475  1.113018 -0.001483
2000-01-07  0.303269  0.021034  0.471715
2000-01-10  1.149815  0.686696 -1.230991
2000-01-11 -1.296118 -0.172950 -0.603887
2000-01-12 -1.034574 -0.523238  0.626968
2000-01-13 -0.193280  1.857499 -0.046383
2000-01-14 -1.043492 -0.820525  0.868685

In [35]: df2.comb
df2.combine        df2.combineAdd     df2.combine_first  df2.combineMult    

In [35]: df2.combine_first(df1)
Out[35]: 
                   A         B         C         D
2000-01-03  0.638998  1.277361  0.193649  0.345063
2000-01-04 -0.816756 -1.711666 -1.155077 -0.678726
2000-01-05  0.435507 -0.025162 -1.112890  0.324111
2000-01-06 -0.210756 -1.027164  0.036664  0.884715
2000-01-07 -0.821631 -0.700394 -0.706505  1.193341
2000-01-10  1.015447 -0.909930  0.027548  0.258471
2000-01-11 -0.497239 -0.979071 -0.461560  0.447598
2000-01-12 -1.034574 -0.523238  0.626968       NaN
2000-01-13 -0.193280  1.857499 -0.046383       NaN
2000-01-14 -1.043492 -0.820525  0.868685       NaN

Tenga en cuenta que toma los valores de df1 para índices que no se superponen con df2. Si esto no hace exactamente lo que desea, estaría dispuesto a mejorar esta función/agregarle opciones.

  • definitivamente la mejor respuesta para fusionar df1 y df2, ¡reemplazando las coincidencias no exactas de df1 con df2!

    –Corina Roca

    13 de enero de 2021 a las 13:26

Avatar de usuario de Nicolás Ozimica
Nicolás Ozimica

Para una fusión como esta, el update El método de un DataFrame es útil.

Tomando los ejemplos de la documentación:

import pandas as pd
import numpy as np

df1 = pd.DataFrame([[np.nan, 3., 5.], [-4.6, 2.1, np.nan],
                   [np.nan, 7., np.nan]])
df2 = pd.DataFrame([[-42.6, np.nan, -8.2], [-5., 1.6, 4]],
                   index=[1, 2])

Datos antes de la update:

>>> df1
     0    1    2
0  NaN  3.0  5.0
1 -4.6  2.1  NaN
2  NaN  7.0  NaN
>>>
>>> df2
      0    1    2
1 -42.6  NaN -8.2
2  -5.0  1.6  4.0

actualicemos df1 con datos de df2:

df1.update(df2)

Datos después de la actualización:

>>> df1
      0    1    2
0   NaN  3.0  5.0
1 -42.6  2.1 -8.2
2  -5.0  1.6  4.0

Observaciones:

  • Es importante notar que esta es una operación “en su lugar”, modificando el DataFrame que llama update.
  • También tenga en cuenta que los valores no NaN en df1 no se sobrescriben con valores NaN en df2

  • Esto es más intuitivo que combine_first porque actúa exactamente como el update método que conocemos de dicts.

    – saroele

    3 de abril de 2017 a las 12:06

  • Tenga en cuenta que DataFrame.update() es un poco diferente a dict porque no agrega nuevos elementos de índice de la misma manera que dict agrega nuevas claves. Ejemplo: gist.github.com/flutefreak7/b4eb6a93565c375d79b791c2bbd672b1

    – monstruo de la flauta7

    30 oct 2020 a las 19:23

  • Deberías usar update solo si está dispuesto a excluir índices exclusivos de df2 Usar combine_first si quieres incluirlos

    – Colin Anthony

    4 de febrero de 2022 a las 7:07


Todavía no encontré una respuesta satisfactoria para esta tarea en la que no es necesario especificar previamente qué columnas se deben usar. lo estoy haciendo combinando merge, renamey drop. df_some_wrong es un marco de datos con importantes columnas nuevas. Sin embargo, tiene algunas columnas antiguas que tienen valores incorrectos y deben sobrescribirse con los valores correctos contenidos en df_correct. Sólo las columnas con valores incorrectos en df_some_wrong se comparten entre df_some_wrong y df_correct.

wrong_suffix = "_wrong"
correct_suffix = "_correct"
# merge, rename shared columns with suffixes
merged_df = df_some_wrong.merge(
    df_correct.
    left_index=True,
    right_index=True,
    suffixes=(wrong_suffix, correct_suffix),
)
# find all the renamed columns from df_correct
rename_and_drop_cols = [
    col for col in merged_df.columns if col.endswith(correct_suffix)
]
# dict that describes how correct columns should be renamed
# to old column name
rename_cols = {
    key: key.replace(correct_suffix, "") for key in rename_and_drop_cols
}
# list describing the wrong columns that can be dropped
drop = [
    col.replace(correct_suffix, wrong_suffix) for col in rename_and_drop_cols
]
# finally rename and drop
merged_df = merged_df.rename(rename, axis=1).drop(drop, axis=1)

¿Ha sido útil esta solución?