Cómo combinar dataframes en R

Publicado el 21 abril 2021 por Daniel Rodríguez @analyticslane

Suele ser habitual que los conjuntos de datos con los que trabajamos no se encuentren en una única tabla. Por ejemplo, los datos que identifican al cliente y las operaciones que este ha realizado. Una forma puede ser unirlos en una base de datos mediante un comando SQL. Aunque también se pueden combinar dataframes en R directamente, usando para ello la función merge().

Conjunto de datos de ejemplo

Para poder combinar dataframes en R vamos a crear primero dos conjuntos de datos. Un primer conjunto llamado clients en el que se guardaran los datos de cada uno de los clientes: id, nombre y edad. Además de este dataframe, también se creará un segundo con los datos de facturación que son: id de la factura, id del cliente y cantidad. Datos que se van a crear con el siguiente código.

clients <- data.frame(
  id = c(1, 2, 3, 4, 5),
  first_name = c('Oralie' ,'Imojean' ,'Michele', 'Ailbert', 'Stevy'),
  last_name = c('Fidgeon' ,'Benet' ,'Woodlands', 'Risdale', 'MacGorman'),
  age = c(30 ,21 ,29 ,22, 24))

invoices <- data.frame(
  invoice_id = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),
  client_id = c(3, 2, 7, 2, 7, 3, 1, 4 ,2, 3, 6, 2),
  amount = c(77.91, 24.36, 74.65, 19.75, 27.46, 17.13, 45.77, 81.7, 14.41, 52.69, 32.03, 12.78))

Estos son los mismos datos que hemos utilizado en su ocasión para explicar cómo combinar datos en Python.

Combinación básica de los datos

Ahora nos podemos plantear como combinar ambos dataframes en uno que contenga los datos de clientes y facturas. Conservando únicamente los clientes que han comprado y las facturas que tienen un cliente. Para lo que se puede hacer una unión de ambos mediante la función merge().

merge(x = clients, y = invoices, by.x = 'id', by.y = 'client_id')

Expresión en la que se indica que se unan los datos clients con los datos de invoices usando para ello la clave id en el primer objeto y client_id en el segundo. Si el identificador tuviese el mismo nombre en ambos objetos se podría usar únicamente la propiedad by para indicarlo. Pudiendo omitir en este caso by.x y by.y. Al ejecutar esta línea de código se obtiene el siguiente resultado

   id first_name last_name age invoice_id amount
 1  1     Oralie   Fidgeon  30          7  45.77
 2  2    Imojean     Benet  21          2  24.36
 3  2    Imojean     Benet  21          4  19.75
 4  2    Imojean     Benet  21          9  14.41
 5  2    Imojean     Benet  21         12  12.78
 6  3    Michele Woodlands  29          6  17.13
 7  3    Michele Woodlands  29          1  77.91
 8  3    Michele Woodlands  29         10  52.69
 9  4    Ailbert   Risdale  22          8  81.70

En la que se puede ver que solamente han comprado cuatro clientes. No hay una factura para el cliente 5. Además de comprobar que solo 9 de las doce facturas tienen un cliente registrado.

Incluir todos los clientes (Left Join)

Puede ser que para nuestro análisis queramos incluir todos los clientes, aunque no exista una factura asociada a estos. Lo que se puede hacer mediante una operación "Left Join". Para esto existe hay que asignar el valor verdadero al parámetro all.x de merge(). Lo que se puede hacer con la siguiente línea

merge(x = clients, y = invoices, by.x = 'id', by.y = 'client_id', all.x = TRUE)

Con lo que se obtiene el siguiente resultado.

    id first_name last_name age invoice_id amount
 1   1     Oralie   Fidgeon  30          7  45.77
 2   2    Imojean     Benet  21          2  24.36
 3   2    Imojean     Benet  21          4  19.75
 4   2    Imojean     Benet  21          9  14.41
 5   2    Imojean     Benet  21         12  12.78
 6   3    Michele Woodlands  29          6  17.13
 7   3    Michele Woodlands  29          1  77.91
 8   3    Michele Woodlands  29         10  52.69
 9   4    Ailbert   Risdale  22          8  81.70
 10  5      Stevy MacGorman  24         NA     NA

Ahora se puede ver que el resultado incluye todos los clientes. Aunque para el cliente cinco los valores de la tabla invoices son nulos.

Incluir todas las facturas (Right Join)

Si lo que necesitamos es incluir todas las facturas solamente tenemos que recurrir a una operación tipo "Right Join". Operación que de forma análoga a la anterior se puede realizar asignando el valor verdadero al parámetro all.x. Esto es, como se muestra a continuación

merge(x = clients, y = invoices, by.x = 'id', by.y = 'client_id', all.y = TRUE)

Con lo que se obtienen los siguientes resultados

    id first_name last_name age invoice_id amount
 1   1     Oralie   Fidgeon  30          7  45.77
 2   2    Imojean     Benet  21          2  24.36
 3   2    Imojean     Benet  21          4  19.75
 4   2    Imojean     Benet  21          9  14.41
 5   2    Imojean     Benet  21         12  12.78
 6   3    Michele Woodlands  29          6  17.13
 7   3    Michele Woodlands  29          1  77.91
 8   3    Michele Woodlands  29         10  52.69
 9   4    Ailbert   Risdale  22          8  81.70
 10  6         NA        NA  NA         11  32.03
 11  7         NA        NA  NA          5  27.46
 12  7         NA        NA  NA          3  74.65

Al igual que el el caso anterior los registros que no tienen valores son nulos en el cruce.

Incluir todos los registros

Finalmente, también se puede incluir todos los registros asignando el valor verdadero a la propiedad all. Esto es, se puede incluir todos los clientes, aunque no tengan factura y todos los clientes, aunque no exista un cliente ejecutando el siguiente código

merge(x = clients, y = invoices, by.x = 'id', by.y = 'client_id', all = TRUE)

Lo que nos da el resultado esperado

    id first_name last_name age invoice_id amount
 1   1     Oralie   Fidgeon  30          7  45.77
 2   2    Imojean     Benet  21          2  24.36
 3   2    Imojean     Benet  21          4  19.75
 4   2    Imojean     Benet  21          9  14.41
 5   2    Imojean     Benet  21         12  12.78
 6   3    Michele Woodlands  29          6  17.13
 7   3    Michele Woodlands  29          1  77.91
 8   3    Michele Woodlands  29         10  52.69
 9   4    Ailbert   Risdale  22          8  81.70
 10  5      Stevy MacGorman  24         NA     NA
 11  6        NA         NA  NA         11  32.03
 12  7        NA         NA  NA          5  27.46
 13  7        MA         NA  NA          3  74.65

Conclusiones

En esta ocasión hemos visto cómo se puede usar la función merge() para combinar dataframes en R. Una operación que es muy habitual y, gracias a esta función, se puede hacer dentro de nuestras sesiones de R.

Image by Ulrike Leone from Pixabay