Pandas: El método merge de Pandas

Publicado el 15 febrero 2021 por Daniel Rodríguez @analyticslane

Hace tiempo hemos visto una entrada en la que se explicaba cómo unir y combinar objetos DataFrame en Pandas. Una entrada en la que se había utilizado los métodos concat y merge. El método merge de Pandas ofrece muchas posibilidades, por lo que vamos a ver las opciones que nos ofrece.

El método merge de Pandas

En Pandas existe el método merge() con el que se pueden combinar los datos de dos objetos DataFrame de forma bastante eficiente. Este método requiere que se le pase como parámetros dos DataFrame e instrucciones para combinar los mismos. Básicamente la especificación de este método es:

pd.merge(
    left,
    right,
    how='inner',
    on=None,
    left_on=None,
    right_on=None,
    left_index: False,
    right_index: False,
    sort: False,
    suffixes=('_x', '_y'),
    copy: bool = True,
    indicator: bool = False,
    validate=None)
  • left: el primer objeto DataFrame que se desea combinar.
  • right: el segundo objeto DataFrame que se desea combinar.
  • how: la forma en la que se desean combinar los objetos, las opciones son similares a las que existen en las uniones SQL:
    • left: incluye los valores del primer objeto DataFrame y los del segundo que cumplan la condición.
    • right: incluye los valores del segundo objeto DataFrame y los del primero que cumplan la condición de unión.
    • outer: con esta opción se incluyen tanto los valores del primer como del segundo objeto, aunque no cumplan la condición.
    • inner: esta es la opción por defecto y solamente devuelve los registros de ambos objetos DataFrame que cumplan la condición de unión.
  • on: es el nombre de la columna de ambos objetos por cuyo valor se unen los objetos DataFrame. En caso de que no se pase ningún valor los objetos se unirán mediante los indices. En caso de que el nombre de la columna mediante la que se desea unir los objetos no es el mismo en ambos se deberá usar los parámetros left_on y right_on para indicar el nombre del primero y segundo objeto.
  • left_index y right_index: en caso de que se indique el valor verdadero se usarán los índices del primer y segundo objeto respectivamente para realizar la unión.
  • sort: en caso de que se indique la opción True ordenará el resultado en base al orden de la unión. Esta opción reduce el rendimiento del debito al proceso de unión.
  • suffixes: es una tupla de textos en la que se indican sufijos a utilizar en caso de que exista el mismo nombre el ambos DataFrame.
  • copy: se utiliza para indicar si los valores del objeto se copiaran o no.
  • indicator: al seleccionarse agrega una columna al DataFrame de salida llamada _merge con información sobre el origen de cada fila. _merge es de tipo categórico y toma un valor de left_only para las observaciones cuya clave de fusión solo aparece en el primer DataFrame, right_only para las observaciones cuya clave de fusión solo aparece en el segundo DataFrame o both si la clave de fusión de la observación se encuentra en ambos.
  • validate: en el caso que se especifique, comprueba si la combinación es del tipo indicado: one_to_one, one_to_many, many_to_one o many_to_many.

Ejemplos de uso del método merge

Supongamos que tenemos unos datos de clientes y las compras que han realizado. Datos similares a los que hemos utilizado en la entrada " Unir y combinar DataFrame con Pandas ". Conjunto de datos que se puede crear con el siguiente código Python.

import pandas as pd

clients = {'client': [1, 2, 3, 4, 5],
           'store': [1, 2, 2, 3, 4],
           'first' : ['Oralie' ,'Imojean' ,'Michele', 'Ailbert', 'Stevy'],
           'last' : ['Fidgeon' ,'Benet' ,'Woodlands', 'Risdale', 'MacGorman'],
           'age' : [30 ,21 ,29 ,22, 24]}

clients = pd.DataFrame(clients)

invoices = {'invoice': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
            'store': [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3],
            'client' : [3, 2, 7, 2, 7, 3, 1, 4 ,2, 3, 6, 2],
            'amount': [77.91, 24.36, 74.65, 19.75, 27.46, 17.13, 45.77, 81.7, 14.41, 52.69, 32.03, 12.78]}

invoices = pd.DataFrame(invoices)
   client  store    first       last  age
0       1      1   Oralie    Fidgeon   30
1       2      2  Imojean      Benet   21
2       3      2  Michele  Woodlands   29
3       4      3  Ailbert    Risdale   22
4       5      4    Stevy  MacGorman   24

    invoice  store  client  amount
0         1      1       3   77.91
1         2      2       2   24.36
2         3      3       7   74.65
3         4      1       2   19.75
4         5      2       7   27.46
5         6      3       3   17.13
6         7      1       1   45.77
7         8      2       4   81.70
8         9      3       2   14.41
9        10      1       3   52.69
10       11      2       6   32.03
11       12      3       2   12.78

En estos conjuntos de datos se puede ver los datos de los clientes que están asociados a una tienda, aunque pueden comprar en otra, y las diferentes facturas que de los clientes. Ahora podemos unir a los clientes con las facturas para tener una única tabla.

pd.merge(clients, invoices, on='client')
   client  store_x    first       last  age  invoice  store_y  amount
0       1        1   Oralie    Fidgeon   30        7        1   45.77
1       2        2  Imojean      Benet   21        2        2   24.36
2       2        2  Imojean      Benet   21        4        1   19.75
3       2        2  Imojean      Benet   21        9        3   14.41
4       2        2  Imojean      Benet   21       12        3   12.78
5       3        2  Michele  Woodlands   29        1        1   77.91
6       3        2  Michele  Woodlands   29        6        3   17.13
7       3        2  Michele  Woodlands   29       10        1   52.69
8       4        3  Ailbert    Risdale   22        8        2   81.70

Algo que puede ser de interés es buscar los clientes que no han realizado ninguna compra en el perdido donde se han registrados los datos. Para ello se puede cambiar el modo de unión a left y seleccionar los registros que son nulos en el conjunto resultante.

not_invoices = pd.merge(clients, invoices, on='client', how='left')
not_invoices.loc[not_invoices['invoice'].isnull()]
   client  store_x  first       last  age  invoice  store_y  amount
9       5        4  Stevy  MacGorman   24      NaN      NaN     NaN

Con lo que se puede describir que hay un cliente que no ha comprado.

Algo que se puede hacer análoga es ver los clientes que están registrados, lo que se puede conseguir cambiando el modo de unión a right.

not_client = pd.merge(clients, invoices, on='client', how='right')
not_client.loc[not_client['first'].isnull()]
    client  store_x first last  age  invoice  store_y  amount
9        7      NaN   NaN  NaN  NaN        3        3   74.65
10       7      NaN   NaN  NaN  NaN        5        2   27.46
11       6      NaN   NaN  NaN  NaN       11        2   32.03

Con lo que se puede observar que hay dos clientes que no están registrados pero han comprado en alguna tienda durante el periodo.

Conclusiones

En esta ocasión hemos repasado las principales propiedades del método merge() de Pandas. Un método que nos permite combinar los datos objetos DataFrame de una forma similar a cómo se puede hacer con SQL.