Programación en R para Data Science

Uniendo dataframes en R

Author

Jesús Turpín

Published

October 24, 2023

Introducción

Aunque en R existe la función merge(), vamos a seguir trabajando con la familia de verbos de dplyr Vamos a utilizar 2 data frame sencillos para entender su funcionamiento.

Ayuda Tidyverse

 pedidos <- data.frame(ClienteId = c(1:5), Producto = c("Televisión", "Smartphone", "Frigorífico", "Lavadora", "Microondas"))
 
 clientes <- data.frame(ClienteId = c(1:8), Nombre = c("Juan", "Jose", "Antonio", "Luis", "Ismael", "David", "Jesús", "Ana"), Ciudad = c("Murcia", "Murcia", "Madrid", "Madrid", "Madrid", "Albacete", "Toledo", "Barcelona"))
pedidos
  ClienteId    Producto
1         1  Televisión
2         2  Smartphone
3         3 Frigorífico
4         4    Lavadora
5         5  Microondas
clientes
  ClienteId  Nombre    Ciudad
1         1    Juan    Murcia
2         2    Jose    Murcia
3         3 Antonio    Madrid
4         4    Luis    Madrid
5         5  Ismael    Madrid
6         6   David  Albacete
7         7   Jesús    Toledo
8         8     Ana Barcelona

Uniendo tablas por columnas

INNER JOIN

Si la columna de unión tiene el mismo nombre en ambos data frames:

library(dplyr)

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
pedidos_clientes <- pedidos %>%
inner_join(clientes, by = "ClienteId")
pedidos_clientes
  ClienteId    Producto  Nombre Ciudad
1         1  Televisión    Juan Murcia
2         2  Smartphone    Jose Murcia
3         3 Frigorífico Antonio Madrid
4         4    Lavadora    Luis Madrid
5         5  Microondas  Ismael Madrid

Ahora la columna Id, no se llama ClienteId

clientes <- data.frame(Id = c(1:8), Nombre = c("Juan", "Jose", "Antonio", "Luis", "Ismael", "David", "Jesús", "Ana"), Ciudad = c("Murcia", "Murcia", "Madrid", "Madrid", "Madrid", "Albacete", "Toledo", "Barcelona"))
clientes
  Id  Nombre    Ciudad
1  1    Juan    Murcia
2  2    Jose    Murcia
3  3 Antonio    Madrid
4  4    Luis    Madrid
5  5  Ismael    Madrid
6  6   David  Albacete
7  7   Jesús    Toledo
8  8     Ana Barcelona

Si el nombre de las columnas de unión es distinto:

pedidos_clientes <- pedidos %>%
inner_join(clientes, by = c("ClienteId" = "Id"))
pedidos_clientes
  ClienteId    Producto  Nombre Ciudad
1         1  Televisión    Juan Murcia
2         2  Smartphone    Jose Murcia
3         3 Frigorífico Antonio Madrid
4         4    Lavadora    Luis Madrid
5         5  Microondas  Ismael Madrid

LEFT JOIN

clientes <- data.frame(ClienteId = c(1:8), Nombre = c("Juan", "Jose", "Antonio", "Luis", "Ismael", "David", "Jesús", "Ana"), Ciudad = c("Murcia", "Murcia", "Madrid", "Madrid", "Madrid", "Albacete", "Toledo", "Barcelona"))
clientes
  ClienteId  Nombre    Ciudad
1         1    Juan    Murcia
2         2    Jose    Murcia
3         3 Antonio    Madrid
4         4    Luis    Madrid
5         5  Ismael    Madrid
6         6   David  Albacete
7         7   Jesús    Toledo
8         8     Ana Barcelona
clientes_pedidos <- clientes %>%
left_join(pedidos, by = c("ClienteId"))
clientes_pedidos
  ClienteId  Nombre    Ciudad    Producto
1         1    Juan    Murcia  Televisión
2         2    Jose    Murcia  Smartphone
3         3 Antonio    Madrid Frigorífico
4         4    Luis    Madrid    Lavadora
5         5  Ismael    Madrid  Microondas
6         6   David  Albacete        <NA>
7         7   Jesús    Toledo        <NA>
8         8     Ana Barcelona        <NA>

RIGHT JOIN

pedidos_clientes <- pedidos %>%
right_join(clientes, by = c("ClienteId"))
pedidos_clientes
  ClienteId    Producto  Nombre    Ciudad
1         1  Televisión    Juan    Murcia
2         2  Smartphone    Jose    Murcia
3         3 Frigorífico Antonio    Madrid
4         4    Lavadora    Luis    Madrid
5         5  Microondas  Ismael    Madrid
6         6        <NA>   David  Albacete
7         7        <NA>   Jesús    Toledo
8         8        <NA>     Ana Barcelona

FULL JOIN

productos <- data.frame(Producto = c("Televisión", "Smartphone", "Frigorífico", "Lavadora", "Microondas", "Estufa", "Tablet", "Ordenador"), Precio = c(600,500,800,400,80,20,200,1200))
productos
     Producto Precio
1  Televisión    600
2  Smartphone    500
3 Frigorífico    800
4    Lavadora    400
5  Microondas     80
6      Estufa     20
7      Tablet    200
8   Ordenador   1200
pedidos %>%
full_join(productos, by = c("Producto")) 
  ClienteId    Producto Precio
1         1  Televisión    600
2         2  Smartphone    500
3         3 Frigorífico    800
4         4    Lavadora    400
5         5  Microondas     80
6        NA      Estufa     20
7        NA      Tablet    200
8        NA   Ordenador   1200
pedidos %>%
full_join(productos, by = c("Producto")) %>%
full_join(clientes, by = c("ClienteId"))
   ClienteId    Producto Precio  Nombre    Ciudad
1          1  Televisión    600    Juan    Murcia
2          2  Smartphone    500    Jose    Murcia
3          3 Frigorífico    800 Antonio    Madrid
4          4    Lavadora    400    Luis    Madrid
5          5  Microondas     80  Ismael    Madrid
6         NA      Estufa     20    <NA>      <NA>
7         NA      Tablet    200    <NA>      <NA>
8         NA   Ordenador   1200    <NA>      <NA>
9          6        <NA>     NA   David  Albacete
10         7        <NA>     NA   Jesús    Toledo
11         8        <NA>     NA     Ana Barcelona

Uniendo tablas por filas

UNION

Combina todas las filas de ambos data frames y elimina las duplicadas. El número de columnas debe coincidir.

pedidos_ayer <- data.frame(ClienteId = c(1:5), Producto = c("Televisión", "Smartphone", "Frigorífico", "Lavadora", "Microondas"))
pedidos_hoy <- data.frame(ClienteId = c(4:8), Producto = c("Lavadora", "Microondas", "Ordenador", "Estufa", "Tablet"))
pedidos_ayer
  ClienteId    Producto
1         1  Televisión
2         2  Smartphone
3         3 Frigorífico
4         4    Lavadora
5         5  Microondas
pedidos_hoy
  ClienteId   Producto
1         4   Lavadora
2         5 Microondas
3         6  Ordenador
4         7     Estufa
5         8     Tablet
union(pedidos_ayer, pedidos_hoy)
  ClienteId    Producto
1         1  Televisión
2         2  Smartphone
3         3 Frigorífico
4         4    Lavadora
5         5  Microondas
6         6   Ordenador
7         7      Estufa
8         8      Tablet

UNION ALL

union_all(pedidos_ayer, pedidos_hoy)
   ClienteId    Producto
1          1  Televisión
2          2  Smartphone
3          3 Frigorífico
4          4    Lavadora
5          5  Microondas
6          4    Lavadora
7          5  Microondas
8          6   Ordenador
9          7      Estufa
10         8      Tablet

Filtrando filas mediante otras tablas

SEMI JOIN

Sirve para filtrar filas de una tabla que aparecen en otra. No agrega columnas adicionales. Vamos a mostrar la tabla clientes, que han realizado un pedido hoy:

clientes
  ClienteId  Nombre    Ciudad
1         1    Juan    Murcia
2         2    Jose    Murcia
3         3 Antonio    Madrid
4         4    Luis    Madrid
5         5  Ismael    Madrid
6         6   David  Albacete
7         7   Jesús    Toledo
8         8     Ana Barcelona
pedidos_hoy
  ClienteId   Producto
1         4   Lavadora
2         5 Microondas
3         6  Ordenador
4         7     Estufa
5         8     Tablet
clientes_activos_hoy <- semi_join(clientes, pedidos_hoy, by=c("ClienteId"))
clientes_activos_hoy
  ClienteId Nombre    Ciudad
1         4   Luis    Madrid
2         5 Ismael    Madrid
3         6  David  Albacete
4         7  Jesús    Toledo
5         8    Ana Barcelona

ANTI JOIN

Filtra filas de una tabla que NO aparecen en la otra. No agrega columnas adicionales. Vamos a mostrar la tabla clientes, que no hicieron pedido hoy:

clientes_inactivos_hoy <- anti_join(clientes, pedidos_hoy, by=c("ClienteId"))
clientes_inactivos_hoy
  ClienteId  Nombre Ciudad
1         1    Juan Murcia
2         2    Jose Murcia
3         3 Antonio Madrid

Librería SQLDF

Para los más familiarizados con SQL, existe el paquete sqldf que permite escribir queries SQL “al vuelo” sobre los data frames en R existentes en memoria. No es óptimo para grandes cantidades de datos.

library(sqldf)
sqldf('SELECT * FROM pedidos p INNER JOIN clientes c ON p.ClienteId = c.ClienteId')
  ClienteId    Producto ClienteId  Nombre Ciudad
1         1  Televisión         1    Juan Murcia
2         2  Smartphone         2    Jose Murcia
3         3 Frigorífico         3 Antonio Madrid
4         4    Lavadora         4    Luis Madrid
5         5  Microondas         5  Ismael Madrid

Resumen, alternativas y referencias

Repositorio data_preparation_r

(datasciencemadesimple.com 2020)

References

datasciencemadesimple.com. 2020. “Datasciencemadesimple.” https://www.datasciencemadesimple.com/.