Combinación de dataframes en R feature image

Combinación de dataframes en R

9 mins

La 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

@pmoracho QR code
https://pmoracho.github.io/blog/2017/06/26/Combinacion-de-datos-en-R/
26-Jun-17
BY-NC-SA 4.0 https://pmoracho.github.io/disclosure
https://pmoracho.github.io/blog/2017/06/26/Combinacion-de-datos-en-R/