11.5 Cruces de tablas
Con la función merge
pueden hacerse cruces de tablas. Para ilustrar los distintos tipos de cruce, crearemos unos datos pequeños de ejemplo:
clientes <- data.frame(id = 1:3, nombre = c("Carlos", "Sara", "Raquel"))
ventas <- data.frame(fecha = c(1, 1, 1, 2, 2, 3, 3, 3, 4),
id = c(1,2,3,2,3, 1, 2, 3, 3),
total = 100 * runif(9))
Para cruzarlas por defecto, se usa la función merge
:
merge(clientes, ventas)
## id nombre fecha total
## 1 1 Carlos 1 75.04759
## 2 1 Carlos 3 41.64581
## 3 2 Sara 3 78.36645
## 4 2 Sara 2 90.88009
## 5 2 Sara 1 24.15553
## 6 3 Raquel 2 95.34162
## 7 3 Raquel 1 61.04433
## 8 3 Raquel 3 81.18654
## 9 3 Raquel 4 98.56591
Esta función crea una nueva tabla juntando filas de otras dos. El resultado es el mismo que la consulta de SQL
select *
from clientes a, ventas b
where a.id = b.id
merge
junta las filas que tienen el mismo valor en los campos de cruce. Por defecto, los campos de cruce son aquellos que se llaman igual en ambas tablas. Esto es a la vez cómodo (evita tener que especificarlas explícitamente) y peligroso. En el ejercicio siguiente se te pide que investigues cómo modificar este funcionamiento por defecto de merge
.
¿Y si las variables de cruce no se llaman igual? ¿Y si no quieres cruzar por todas ellas?
merge
también permite realizar left joins. Nótese la diferencia entre las dos tablas creadas por merge
en el ejemplo siguiente.
ventas.2 <- ventas[ventas$fecha == 2,]
merge(clientes, ventas.2)
## id nombre fecha total
## 1 2 Sara 2 90.88009
## 2 3 Raquel 2 95.34162
merge(clientes, ventas.2, all.x = T)
## id nombre fecha total
## 1 1 Carlos NA NA
## 2 2 Sara 2 90.88009
## 3 3 Raquel 2 95.34162
La consulta de SQL equivalente a la última expresión es
select *
from clientes a left join ventas.2 b
on a.id = b.id
Para el ejercicio siguiente vamos a crear una tabla simulada,
n <- 10000
n.clientes <- 1000
contracts <- data.frame(
customer = sample(n.clientes, n, replace = T),
contract = sample(n, n),
amount = 1000 * exp(runif(n))
)
que contiene clientes, contratos y el importe de cada contrato.
Calcula el porcentaje que cada contrato de un cliente supone dentro de su facturación total. P.e., si un cliente tiene dos contratos de 200 y 800 euros, a la primera fila le asociaremos un 20% y, a la segunda, 80%. Una manera de hacerlo consiste en:
- Crear una tabla que agregue el total de los importes por cliente
- Cruzar esta nueva tabla con la original (por cliente)
- Dividir el importe original por el total y multiplicarlo por 100.
merge
es la función por defecto para cruzar tablas en R. Sin embargo, existe una colección de funciones (left_join
, inner_join
, etc.) en el paquete dplyr
que pueden resultar más familiares a quienes tengan experiencia con SQL29.