Capítol 7 Cruces entre tablas

7.1 Ordenación y Union

Ordenación

Para ordenar un vector se utiliza la función sort().

a <- c(5,2,9,4)
sort(a)
## [1] 2 4 5 9

Lo mismo se puede hacer en dos pasos. Primero, con order() se obtienen los índices de ordenación.

indices_ordenacion <- order(a)
indices_ordenacion
## [1] 2 4 1 3

Segundo se seleccionan los elementos del vector a en ese orden.

a[indices_ordenacion]
## [1] 2 4 5 9

Observa que el resultado es idéntico a utilizar directamente sort().

Mismo principio ahora, para ordenar la tabla paises07 por continente (decreciente) y esperanza de vida (creciente).

library(datos)
library(ggrepel)
suppressPackageStartupMessages(library(tidyverse))

paises07 <- as.data.frame(paises %>% filter(anio==2007))
paises07Ord <- paises07[order(paises07$continente,paises07$esperanza_de_vida
                              ,decreasing = c(T,F)),]
kable(head(paises07Ord))
pais continente anio esperanza_de_vida poblacion pib_per_capita
92 Nueva Zelanda Oceanía 2007 80.204 4115771 25185.009
6 Australia Oceanía 2007 81.235 20434176 34435.367
132 Turquía Europa 2007 71.777 71158647 8458.276
107 Rumania Europa 2007 72.476 22276056 10808.476
16 Bulgaria Europa 2007 73.005 7322858 10680.793
57 Hungría Europa 2007 73.338 9956108 18008.944

Unión por columnas

Para unir las columnas de 2 tablas que comparten ordenación de sus filas se utiliza cbind().

a1 <- paises07[,1:2]
a2 <- paises07[,4:5]
a <- cbind(a1, a2)
kable(head(a))
pais continente esperanza_de_vida poblacion
Afganistán Asia 43.828 31889923
Albania Europa 76.423 3600523
Argelia África 72.301 33333216
Angola África 42.731 12420476
Argentina Américas 75.320 40301927
Australia Oceanía 81.235 20434176

Unión por filas

Unir las filas de dos tablas con la misma ordenación de sus columnas rbind().

a1 <- paises07[1:2,]
a2 <- paises07[4:5,]
a <- rbind(a1, a2)
kable(head(a))
pais continente anio esperanza_de_vida poblacion pib_per_capita
1 Afganistán Asia 2007 43.828 31889923 974.5803
2 Albania Europa 2007 76.423 3600523 5937.0295
4 Angola África 2007 42.731 12420476 4797.2313
5 Argentina Américas 2007 75.320 40301927 12779.3796

7.2 Cruce por campos clave

Un campo clave consiste en una variable que identifica cada registro de forma única.

Por ejemplo, pais y continente son campos clave ya que identifican de forma única a sus respectivas entidades en la tabla de paises.

Antes de realizar cualquier cruce por campos clave, es importante saber si éste tiene o no duplicados.

Unicidad

Para obtener las claves únicas de un vector utiliza unique().

sort(unique(as.character(paises07$continente)))
## [1] "África"   "Américas" "Asia"     "Europa"   "Oceanía"

Para saber qué filas de un data frame están duplicadas, utiliza duplicated().

paisesDup <- paises07[c(1,1,2,3,3,4,5,5,6),]
any(duplicated(paisesDup))    # ¿Tiene duplicados?
## [1] TRUE
as.character(paisesDup$pais[duplicated(paisesDup)]) # que países son
## [1] "Afganistán" "Argelia"    "Argentina"

Fusión con claves

Para cruzar 2 tablas con claves, utiliza merge().

Inner join

Analiza el siguiente ejemplo:

a1 <- data.frame(ID = c(1,2,3), X1 = c(1,1,2), X2 = c("b","a","a"))
a2 <- data.frame(ID = c(2,3,3,4), X1 = c(1,1,2,2), X3 = c(FALSE, TRUE, FALSE, FALSE))
a_inner <- merge(a1, a2)

kable(a_inner)
ID X1 X2 X3
2 1 a FALSE
3 2 a FALSE

R, ha seleccionado ID y X1 como campos clave porque son las variables con nombres coincidentes en ambas tablas. Veremos cómo modificar esto.

Otra decisión que R ha tomado, es que sólo ha recuperado los registros con valores de ID y X1 compartidos en ambas tablas. Este comportamiento en el lenguaje SQL, es conocido como INNER JOIN.

Full join

Para conservar todos los registros de las tablas originales, tanto de la tabla izquierda como derecha, coincida o no, se utiliza el parámetro all=TRUE.

a_full <- merge(a1, a2, all = TRUE)

kable(a_full)
ID X1 X2 X3
1 1 b NA
2 1 a FALSE
3 1 NA TRUE
3 2 a FALSE
4 2 NA FALSE

Observa ahora, no ha descartado ningún registro de las tablas origen. Además, ha rellenado con NA los campos que no cruzan. Este comportamiento en SQL es conocido como FULL JOIN .

Left join

Para imponer que conserve todos los valores origen de la tabla izquierda (a1) y que descarte los de la taba derecha que no sean compartidos utiliza all.x=TRUE.

a_left <- merge(a1, a2, all.x = TRUE)
kable(a_left)
ID X1 X2 X3
1 1 b NA
2 1 a FALSE
3 2 a FALSE

Vemos que ID=1 ahora está presente y ID=4 ha quedado descartado. También que ID=3 sólo aparece una vez. Este comportamiento en SQL, es conocido como LEFT JOIN .

Right join

Para preservar todos los valores de la tabla derecha utiliza all.y=TRUE. Este comportamiento en SQL es el conocido como RIGHT JOIN.

a_right <- merge(a1, a2, all.y = TRUE)
kable(a_right)
ID X1 X2 X3
2 1 a FALSE
3 1 NA TRUE
3 2 a FALSE
4 2 NA FALSE

Ahora ID=3 aparece 2 veces. También aparece ID=4.

Definción de las claves

Para definir las claves del cruce, es necesario pasar como parámetro los nombre de las variables:

  • Cuando los nombres de los campos clave son compartidos en ambas tablas, utiliza by.
  • Cuando hay cambios de nombre, utiliza by.x y by.y

El siguiente ejemplo, realiza un FULL JOIN definiendo como clave la variable ID.

a_comparte <- merge(a1, a2, all.x=TRUE, by = c("ID")) 
# de forma equivalente
a_comparte <- merge(a1, a2, all.x=TRUE, by.x = c("ID"), by.y = c("ID"))

kable(a_comparte)
ID X1.x X2 X1.y X3
1 1 b NA NA
2 1 a 1 FALSE
3 2 a 1 TRUE
3 2 a 2 FALSE

R ha añadido el sufijo .x y .y a X1, porque es una variable compartida que ahora no es clave para el cruce. Observa también que ID=3 aparece 2 veces ya que está duplicado en la tabla a2.