Combinación de dataframes en R
26 Jun 2017 9 minsLa transición entre SQL
y R
puede resultar complicada al principio, pero teniendo clara algunas pautas vamos a ver que no es tan así. Hoy vamos a estudiar los mecanismos de combinación de datos, esto en SQL es el ABC, estamos hablando de la familia de sentencias JOIN
. En R
contrariamente a lo que uno naturalmente pensaría, estas operaciones suelen ser mucho más simples de realizar. En principio, vamos a asumir que un data.frame en R
equivale a una tabla o recordset de datos en SQL, no es tan así pero para este ejemplo nos alcanza.
Vamos a “jugar” entonces con dos data.frame o tablas: clientes
y ventas
, el primero obviamente representa un conjunto de clientes y el segundo las eventuales ventas acumuladas de los mismos, los creamos así:
clientes = data.frame(ClienteId = c(1:4),
RazonSocial = c("Cliente 1", "Cliente 2", "Cliente 3", "Cliente 4"))
ventas = data.frame(ClienteId = c(1, 2, 3, 5),
Monto = c(110, 50, 60, 90))
En definitiva así son ambos:
> clientes
ClienteId RazonSocial
1 1 Cliente 1
2 2 Cliente 2
3 3 Cliente 3
4 4 Cliente 4
> ventas
ClienteId Monto
1 1 110
2 2 50
3 3 60
4 5 90
Hay que notar que:
- Puede haber clientes sin ventas, por ejemplo
Cliente 4
- A modo de ejemplo también tenemos
ventas
que no pertenecen a ningún cliente, por ejemplo el registro # 4 que pertenecería a un Cliente 5 inexistente
Veamos ahora las opciones de combinación de datos, en este ejemplo, vamos a trabajar con una rutina estándar de R
se trata de merge
inner join
Todos los registros coincidentes entre ambos data.frame por by="ClienteId"
merge(x = clientes, y = ventas, by = "ClienteId")
ClienteId RazonSocial Monto
1 1 Cliente 1 110
2 2 Cliente 2 50
3 3 Cliente 3 60
Notar que Cliente 4 no tiene ventas por eso no aparece, y obviamente las ventas del cliente inexistente 5 tampoco aparecerán
Left Join
Un clásico left join
dónde se muestra todos los registros del data.frame izquierdo (x
) y solo los coincidentes por ClienteId
de la tabla derecha (y
)
df <-merge(x = clientes, y = ventas, by = "ClienteId", all.x = TRUE)
df
ClienteId RazonSocial Monto
1 1 Cliente 1 110
2 2 Cliente 2 50
3 3 Cliente 3 60
4 4 Cliente 4 NA
Vemos que el Cliente 4 que no tiene registros en el data.frame ventas
muestra la columna de Monto
como NA
, en SQL se nos mostraría el valor NULL
. Algunas veces nos puede servir así, pero en este ejemplo lo correcto sería indicar esta columna en 0 de la siguiente forma:
df$Monto[is.na(df$Monto)] <- 0
df
ClienteId RazonSocial Monto
1 1 Cliente 1 110
2 2 Cliente 2 50
3 3 Cliente 3 60
4 4 Cliente 4 0
Right join
En este caso mostraremos todos los registros del data.frame derecho (y = ventas
) y solo los coincidentes del izquierdo (x = clientes
) y también reeplazamos los valores NA
de las columnas que correspondan.
df <-merge(x = clientes, y = ventas, by = "ClienteId", all.y = TRUE)
ClienteId RazonSocial Monto
1 1 Cliente 1 110
2 2 Cliente 2 50
3 3 Cliente 3 60
4 5 <NA> 90
Modificar el <NA>
en RazonSocial
es algo diferente a lo que hicimos con el monto, debido a que RazonSocial
se convierte en un Factor
, debemos primero transformar la columna en un character
, reemplazar los NA
y reconvertirla nuevamente en Factor
.
df$RazonSocial <- as.character(df$RazonSocial)
df$RazonSocial[is.na(df$RazonSocial)] <- "Sin Cliente"
df$RazonSocial <- factor(df$RazonSocial)
ClienteId RazonSocial Monto
1 1 Cliente 1 110
2 2 Cliente 2 50
3 3 Cliente 3 60
4 5 Sin Cliente 90
Outer Join
Al contrario del inner, el outer va a combinar todos los registros de ambos dataframes, coincidan por ClienteId
o no:
merge(x = clientes, y = ventas, by = "ClienteId", all = TRUE)
ClienteId RazonSocial Monto
1 1 Cliente 1 110
2 2 Cliente 2 50
3 3 Cliente 3 60
4 4 Cliente 4 NA
5 5 <NA> 90
Ahora vemos el Cliente 4 que no tiene ventas y las Ventas del Cliente 5 inexistente. Vemos que las columnas no coincidentes se completan con el valor NA
, en SQL se completan con el valor NULL
.
Cross Join
O producto cartesiano, cada fila de un data.frame se combina con la fila del otro
merge(x = clientes, y = ventas, by = NULL)
ClienteId.x RazonSocial ClienteId.y Monto
1 1 Cliente 1 1 110
2 2 Cliente 2 1 110
3 3 Cliente 3 1 110
4 4 Cliente 4 1 110
5 1 Cliente 1 2 50
6 2 Cliente 2 2 50
7 3 Cliente 3 2 50
8 4 Cliente 4 2 50
9 1 Cliente 1 3 60
10 2 Cliente 2 3 60
11 3 Cliente 3 3 60
12 4 Cliente 4 3 60
13 1 Cliente 1 5 90
14 2 Cliente 2 5 90
15 3 Cliente 3 5 90
16 4 Cliente 4 5 90