Capítulo 4 Uniones de tablas con R

Además de manejar los datos de un data frame en ocasiones es necesario realizar uniones entre conjuntos de datos para crear o añadir nuevas variables a un data frame que es una base de observaciones inicial. Se pueden establecer 2 tipos de uniones fundamentales, uniones verticales de tablas y uniones horizontales. Las uniones verticales serán las concatenaciones de data frames, poner una estructura de datos encima de otra y las uniones horizontales serán las que se denominarán join.

Se emplea una estructura de datos sencilla para ejemplificar el funcionamiento.

library(kableExtra)
library(tidyverse)

df1 <- data.frame(anio = c(2018, 2019, 2020, 2021), variable1=c(10, 20, 30, 40), variable2=c(1000,2000,3000,4000))
df2 <- data.frame(anio = c(2017, 2018, 2019, 2020), variable1=c(50, 60, 70, 80), variable3=c(5000,6000,7000,8000))

df1 %>% kable()
anio variable1 variable2
2018 10 1000
2019 20 2000
2020 30 3000
2021 40 4000
df2 %>% kable()
anio variable1 variable3
2017 50 5000
2018 60 6000
2019 70 7000
2020 80 8000

Se puede observar como se han creado manualmente 2 data frames con lo que trabajaremos y el uso de tidyverse y kable para la visualización de tablas en R. Veamos los principales tipos de uniones.

4.1 Uniones verticales

El siguiente código emplea la función rbind.data.frame para concatenar datos, para poner una tabla encima de otra y generaría un error:

df <- rbind.data.frame(df1, df2)

Error in match.names(clabs, names(xi)) : names do not match previous names

Significa que ambos conjuntos de datos no tienen las mismas variables. En las uniones verticales con la función rbind.data.frame se han de unir las mismas estructuras. En los datos de trabajo no se dispone de la misma estructura por lo que se torna necesario saber que deseamos unir verticalmente, saber que deseamos concatenar. Si deseamos realizar una unión de todos los datos ambas tablas requieren de las mismas variables:

df1$variable3 <- NA
df2$variable2 <- NA

df <- rbind.data.frame(df1, df2) 
df %>% kable()
anio variable1 variable2 variable3
2018 10 1000 NA
2019 20 2000 NA
2020 30 3000 NA
2021 40 4000 NA
2017 50 NA 5000
2018 60 NA 6000
2019 70 NA 7000
2020 80 NA 8000

Se han creado las variables 3 y 2 donde ha sido necesario y ya se está en disposición de concatenar ambos data frames. Observemos como queda el data frame resultante. Es importante puntualizar que se están produciendo duplicidades por la variable anio, cabe preguntarse ¿son necesarias esas duplicidades? Cuando se trabaje con datos es muy importante disponer de un campo identificativo del registro y determinar si existen duplicidades por ese campo.

En cualquier caso, con el paquete dplyr se pueden concatenar data frames mediante la función bind_rows.

df <- bind_rows(df1, df2)
df %>% kable()
anio variable1 variable2 variable3
2018 10 1000 NA
2019 20 2000 NA
2020 30 3000 NA
2021 40 4000 NA
2017 50 NA 5000
2018 60 NA 6000
2019 70 NA 7000
2020 80 NA 8000

El empleo de esta función no es sensible a la necesidad de que ambos conjuntos de datos tengan los mismos nombres de las variables, si eso no ocurre se emplean valores perdidos representados en R como NA para aquellas ocasiones en las que no coincida.

4.2 Uniones horizontales o join

Esta conocida figura recoge en SQL todos los tipos de join:

No se considera ver todos los ejemplos, se estudiarán las uniones más habituales en el trabajo diario.

4.2.1 Inner join

Es la intersección de dos conjuntos de datos. Usamos la función inner_join de dplyr.

df1 <- data.frame(anio = c(2018, 2019, 2020, 2021), variable1=c(10, 20, 30, 40), variable2=c(1000,2000,3000,4000))
df2 <- data.frame(anio = c(2017, 2018, 2019, 2020), variable1=c(50, 60, 70, 80), variable3=c(5000,6000,7000,8000))

df <- inner_join(df1,df2, by='anio')

# Equivale a df <- df1 %>% inner_join(df2, by='anio')
df %>% kable()
anio variable1.x variable2 variable1.y variable3
2018 10 1000 60 6000
2019 20 2000 70 7000
2020 30 3000 80 8000

La unión de ambas estructuras tiene una variable variable1 en común, dplyr entiende que es necesario preservar las variables del conjunto de datos de la derecha, con el sufijo .x, y las variables del conjunto de datos de la izquierda, con el sufijo .y por este motivo es muy relevante determinar que se quiere unir. En los datos de trabajo podríamos saber cuales de los datos de la izquierda coinciden por año con los de la derecha y unir la variable 3.

df2 <- df2 %>% select(-variable1)
df <- inner_join(df1,df2)
## Joining, by = "anio"
df %>% kable()
anio variable1 variable2 variable3
2018 10 1000 6000
2019 20 2000 7000
2020 30 3000 8000

Se ha eliminado la variable1 del df2 como paso previo, es la que ambos conjuntos de datos tienen en común, se realiza la unión y en este caso se ha obviado el campo de unión porque dplyr busca la “unión natural”, el campo en común que es anio en este caso y no es necesario especificar by= con lo que podemos ahorrar código. En el trabajo diario del científico de datos es necesario realizar múltiples uniones de conjuntos de datos por un camo identificativo (roles de las variables), es buena práctica que este campo identificativo tenga el mismo nombre para todos los conjuntos de datos de trabajo.

4.2.2 Left join

Quizá una de las uniones más habituales en el trabajo diario de un científico de datos. Se parte de un conjunto de datos de base y se le añaden nuevas variables por la derecha respetando las observaciones de la izquierda. La función de dplyr usada es left_join.

df1 <- data.frame(anio = c(2018, 2019, 2020, 2021), variable1=c(10, 20, 30, 40))
df2 <- data.frame(anio = c(2017, 2018, 2019, 2020), variable3=c(5000,6000,7000,8000))

df1 <- df1 %>% left_join(df2)
## Joining, by = "anio"
df1 %>% kable()
anio variable1 variable3
2018 10 6000
2019 20 7000
2020 30 8000
2021 40 NA

Se ha añadido por la derecha la variable3 al df1, añadimos una nueva variable a un data frame de base.

4.2.3 Anti join

Vamos se van a seleccionar aquellos registros de una tabla base que no están en otra tabla de cruce.

df1 <- data.frame(anio = c(2018, 2019, 2020, 2021), variable1=c(10, 20, 30, 40))
df2 <- data.frame(anio = c(2017, 2018, 2019, 2020), variable3=c(5000,6000,7000,8000))

df <- df1 %>% anti_join(df2)
## Joining, by = "anio"
df %>% kable()
anio variable1
2021 40

Se observa que no se ha unido ninguna variable, solo se ha seleccionado el registro de df1 que no cruza con df2.

4.2.4 Librería sqldf

Como científicos de datos es importante saber SQL como lenguaje de consulta, si sabemos SQL tenemos la librería sqldf para utilizar directamente SQL sobre data frames de R.

library(sqldf)

df1 <- data.frame(anio = c(2018, 2019, 2020, 2021), variable1=c(10, 20, 30, 40), variable2=c(1000,2000,3000,4000))
df2 <- data.frame(anio = c(2017, 2018, 2019, 2020), variable1=c(50, 60, 70, 80), variable3=c(5000,6000,7000,8000))

# Inner Join
df <- sqldf("select a.anio, a.variable1, variable3 
            from df1 a, df2 b
            where a.anio = b.anio")
df %>% kable()
anio variable1 variable3
2018 10 6000
2019 20 7000
2020 30 8000
# Left join 
df <- sqldf("select a.anio, a.variable1, variable3 
            from df1 a left join df2 b
            on a.anio = b.anio")
df %>% kable()
anio variable1 variable3
2018 10 6000
2019 20 7000
2020 30 8000
2021 40 NA
# Anti Join
df <- sqldf("select * from df1 where anio not in (select anio from df2)")
df %>% kable()
anio variable1 variable2
2021 40 4000

4.3 Duplicidades en las uniones de tablas

Otra situación habitual que se va a encontrar el científico de datos es la aparición de registros duplicados por el campo identificador (ID), es necesario controlar su existencia porque pueden distorsionar el resultado de un análisis.

df1 <- data.frame(anio = c(2018, 2019, 2020, 2021), variable1=c(10, 20, 30, 40))
df2 <- data.frame(anio = c(2017, 2018, 2019, 2020, 2020), variable3=c(5000,6000,7000,8000, 1000))

df <- df1 %>% left_join(df2)
## Joining, by = "anio"
df %>% kable()
anio variable1 variable3
2018 10 6000
2019 20 7000
2020 30 8000
2020 30 1000
2021 40 NA

En este burdo ejemplo df2 tiene duplicado el año 2020 por lo que una left join con ese conjunto de datos por ese campo provocará duplicidades. Una forma de controlarlo será contabilizar por el campo identificativo.

df %>% group_by(anio) %>% summarise(registros=n()) %>% 
  filter(registros>1) %>% kable()
anio registros
2020 2

En el capítulo anterior ya se anotó la importancia de establecer mecanismos de control cuando se trabajen con datos, bien sea visualizaciones de datos agrupaciones, tablas de frecuencia o estadísticos básicos que veremos en posteriores capítulos.

4.4 Referencias

Javier Alvarez Liébana