Capítol 7 Cruces entre tablas
7.1 Ordenación y Union
Ordenación
Para ordenar un vector se utiliza la función sort()
.
<- c(5,2,9,4)
a 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.
<- order(a)
indices_ordenacion 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))
<- as.data.frame(paises %>% filter(anio==2007))
paises07 <- paises07[order(paises07$continente,paises07$esperanza_de_vida
paises07Ord 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()
.
<- paises07[,1:2]
a1 <- paises07[,4:5]
a2 <- cbind(a1, a2) a
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()
.
<- paises07[1:2,]
a1 <- paises07[4:5,]
a2 <- rbind(a1, a2) a
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()
.
<- paises07[c(1,1,2,3,3,4,5,5,6),]
paisesDup 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:
<- data.frame(ID = c(1,2,3), X1 = c(1,1,2), X2 = c("b","a","a"))
a1 <- data.frame(ID = c(2,3,3,4), X1 = c(1,1,2,2), X3 = c(FALSE, TRUE, FALSE, FALSE))
a2 <- merge(a1, a2)
a_inner
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
.
<- merge(a1, a2, all = TRUE)
a_full
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
.
<- merge(a1, a2, all.x = TRUE)
a_left 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.
<- merge(a1, a2, all.y = TRUE)
a_right 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
yby.y
El siguiente ejemplo, realiza un FULL JOIN definiendo como clave la variable ID
.
<- merge(a1, a2, all.x=TRUE, by = c("ID"))
a_comparte # de forma equivalente
<- merge(a1, a2, all.x=TRUE, by.x = c("ID"), by.y = c("ID"))
a_comparte
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
.