El trabajo de la ciencia de datos requiere a veces proceso de
organización para eficientizar el trabajo de manipulación de los mismos.
Hacer este tipo de tareas en Excel requiere de mucho tiempo, pero con
paquetes como tidyr (que pertenece a
tidyverse) permite unir, ordenar y transformar datos.
Es posible para Rstudio unir distintas tablas o bases de datos (en
forma de dataframes) usando tidyr. Este
tipo de funciones son similares a las que vemos en programas de manejo
de bases de datos y tablas como SQL.
Primero instalemos la librería dplyr
Luego carguemos la librería
Las combinaciones más comunes de utilizar para unión de conjuntos,
fuentes de datos, etc son left join,
right join,
inner join y
full join
Iremos paso a paso por cada uno de este tipo de uniones.
left_join()Este consiste en la unión de dos conjuntos de datos en las que se incluye los datos de la tabla de la izquierda (que es la principal) con los valores coincidentes de la tabla secundaria. Se necesita una variable de clave (variable común)
#Tabla 1
matematicas <- data.frame(
id = c(11,12,13,14,15,16),
NMatematicas = c(5,3,7,8,10,6)
)
#Tabla 2.
lengua <- data.frame(
id = c(11,12,13,14,16,17,18),
Nlengua = c(6,7,8,4,9,7,10)
)
#Tabla 3.
historia <- data.frame(
id_alum = c(11,12,13,14,15,17),
Nhistoria = c(8,5,4,6,9,10)
)
#Librería dplyrs: left_join()
left_join(matematicas, historia, by=c("id"= "id_alum"))## id NMatematicas Nhistoria
## 1 11 5 8
## 2 12 3 5
## 3 13 7 4
## 4 14 8 6
## 5 15 10 9
## 6 16 6 NA
right_join()Mantenemos todas las observaciones de la tabla derecha con este comando pero en el caso de la tabla de matemáticas no se considerarán las que no tienen id con la tabla de Lengua (ej: alumno 15).
Los alumnos 17 y 18 poseen un NA al no tener correspondencia en la tabla de matemáticas.
## id NMatematicas Nlengua
## 1 11 5 6
## 2 12 3 7
## 3 13 7 8
## 4 14 8 4
## 5 16 6 9
## 6 17 NA 7
## 7 18 NA 10
inner_join()La función inner_join() del paquete
dplyr en R es una función para combinar
dos marcos de datos (data frames) basándose en una o varias columnas
comunes, algo parecido a lo que se hace con la operación JOIN en SQL. El
resultado de un inner_join() solo contiene
filas para las cuales hay valores coincidentes en ambas tablas.
La sintaxis básica de la función
inner_join() es la siguiente:
## Joining with `by = join_by(id)`
## id NMatematicas Nlengua
## 1 11 5 6
## 2 12 3 7
## 3 13 7 8
## 4 14 8 4
## 5 16 6 9
Al final resultó que:
Se excluye al alumno de la tabla matemáticas: 15 (no existe en la tabla lengua).
Se excluye a los alumnos de la tabla lengua: 17 y 18 (no existen en la tabla matemáticas).
No se generan NA.
full_join()La función full_join() del paquete
dplyr en R se utiliza para unir dos data
frames por una o varias columnas comunes, similar a cómo se realiza una
operación FULL JOIN en SQL. A diferencia de
inner_join(),
full_join() conservará todas las filas de
ambos data frames, independientemente de si hay una coincidencia en las
columnas especificadas. Si no hay coincidencia, los valores de las
columnas del otro data frame se establecerán como
NA.
La sintaxis básica de full_join() es
similar a inner_join():
## Joining with `by = join_by(id)`
## id NMatematicas Nlengua
## 1 11 5 6
## 2 12 3 7
## 3 13 7 8
## 4 14 8 4
## 5 15 10 NA
## 6 16 6 9
## 7 17 NA 7
## 8 18 NA 10
Al final se incluyen todas las observaciones pero el id=15 existe en
la tabla de matemáticas pero no la del lengua (NA). De manera similar a
los id=17 y 18 existen en la tabla de lengua pero no en la de
matemáticas NA.
tidyr?La librería tidyr es una de las librerías más útiles en
el lenguaje de programación R para la manipulación de datos. Es parte
del conjunto de paquetes conocidos como tidyverse diseñados
para la ciencia de datos. La filosofía central del
tidyverse es tener datos ordenados o “tidy data”, donde
cada variable es una columna y cada observación es una fila.
El paquete tidyr proporciona un conjunto de funciones
que ayudan a manipular la estructura de los datos para que se ajusten a
este formato “tidy”. Esto es especialmente útil cuando los datos con los
que estás trabajando inicialmente están en un formato desordenado o
“messy”.
Algunas de las funciones clave en tidyr incluyen:
gather(): Esta función toma múltiples columnas y las
combina en pares de clave-valor, lo que es útil cuando tienes columnas
que son valores, no variables.
spread(): Esta es la operación inversa de
gather(). Toma pares de clave-valor y los propaga a través
de múltiples columnas.
separate(): Esta función divide una columna en
múltiples columnas.
unite(): Esta es la operación inversa de
separate(). Toma múltiples columnas y las combina en una
sola.
Estas funciones son esenciales para hacer que los datos sean más manejables y fáciles de analizar, lo que a su vez facilita el proceso de limpieza de datos y el análisis posterior.
gather()Esta permite la transformación de un conjunto de datos de largo a ancho, el código es:
gather(data, key= "key", value= "value", ...,na.rm=FALSE, convert= FALSE, factor_key=FALSE
data es el conjunto de datos
key es la variable a agrupar (key)
value es el nombre de la variable cuyo valor esta distribuido dentro de la celda.
na.rm=TRUE; se eliminan los valores faltantes.
factor_key= FALSE; los valores se almacenan como vectores, si es TRUE se almacenan como factores.
spread()El comando `spread()` en R, que forma parte de la librería `tidyr`, es utilizado para transformar datos que están en formato largo a formato ancho. Dicho de otro modo, es útil para cambiar la estructura de un conjunto de datos de manera que los valores de una columna variable se conviertan en múltiples columnas.
El funcionamiento básico de `spread()` es tomar dos columnas: una que indica las ‘llaves’ (las futuras columnas en el formato ancho) y otra que indica los ‘valores’ que irán en esas columnas.
Un ejemplo simple ayudará a entenderlo mejor. Imagina un conjunto de datos que registra, en formato largo, las calificaciones de estudiantes en diferentes materias:
library(tidyr)
data <- data.frame(
estudiante = c('Juan', 'Juan', 'Ana', 'Ana'),
materia = c('Matemáticas', 'Historia', 'Matemáticas', 'Historia'),
calificacion = c(90, 85, 95, 88)
)
data_ancho <- spread(data, key = materia, value = calificacion)Es importante mencionar que, aunque `spread()` ha sido ampliamente utilizado, ha sido sucedido por la función `pivot_wider()` en versiones más recientes de la librería `tidyr`, la cual es más flexible y tiene una sintaxis que se busca sea más intuitiva. Por lo tanto, si estás trabajando con versiones más recientes de `tidyr`, te recomendaría considerar el uso de `pivot_wider()` en lugar de `spread()`.
Otro dato importante es que spread() se uitiliza cuando
tenemos una observación dispersa en múltiples filas. (ej. si tenemos
datos de ciudades con una columna llamada “Tipo” de variable que indica
población o área, realmente cada observación está esparcida en dos
filas, una fila para la población y otra para área). Nos permite llevar
un dataset a la forma de una observación por fila.
Pivotante()En el contexto de R y, específicamente, con el paquete
tidyverse, pivotar se refiere a cambiar la
forma de los datos entre formatos “long” (largo) y “wide” (ancho). Esta
funcionalidad se logra principalmente con las funciones
pivot_longer() y
pivot_wider() del paquete
tidyr, que es parte del
tidyverse.
pivot_longer() convierte las columnas
en filas, es para pasar de wide a long format. (Similar al reshape long
en Stata).pivot_wider() convierte las filas en
columnas, es para pasar de formato largo a ancho (long to wide
formant).library(tidyr)
dato_wide<- tibble(Curso_1=c(1,3,4, 3,4, 9, 7, 4, 8,8), Curso_2=c(1,10, 7, 7, 3, 4, 5, 6, 7, 6))
dato_wide %>%
pivot_longer(cols = everything(), names_to = "Variable", values_to = "Valor")## # A tibble: 20 × 2
## Variable Valor
## <chr> <dbl>
## 1 Curso_1 1
## 2 Curso_2 1
## 3 Curso_1 3
## 4 Curso_2 10
## 5 Curso_1 4
## 6 Curso_2 7
## 7 Curso_1 3
## 8 Curso_2 7
## 9 Curso_1 4
## 10 Curso_2 3
## 11 Curso_1 9
## 12 Curso_2 4
## 13 Curso_1 7
## 14 Curso_2 5
## 15 Curso_1 4
## 16 Curso_2 6
## 17 Curso_1 8
## 18 Curso_2 7
## 19 Curso_1 8
## 20 Curso_2 6
Otro ejemplo pero con
pivot_wider():
library(tidyr)
datos_largo <- tibble(variable = c("a", "b", "a", "b"), valor = c(1, 3, 2, 4))
datos_largo %>%
pivot_wider(names_from = variable, values_from = valor)## Warning: Values from `valor` are not uniquely identified; output will contain list-cols.
## • Use `values_fn = list` to suppress this warning.
## • Use `values_fn = {summary_fun}` to summarise duplicates.
## • Use the following dplyr code to identify duplicates.
## {data} %>%
## dplyr::group_by(variable) %>%
## dplyr::summarise(n = dplyr::n(), .groups = "drop") %>%
## dplyr::filter(n > 1L)
## # A tibble: 1 × 2
## a b
## <list> <list>
## 1 <dbl [2]> <dbl [2]>
La capacidad de pivotar datos es esencial para muchas tareas de preparación y análisis de datos. Permite al usuario reformatear fácilmente los datos según cómo se quieran analizar o visualizar. Por ejemplo, algunas funciones de gráficos podrían requerir un formato específico (largo o ancho) para funcionar correctamente, o ciertos modelos estadísticos podrían requerir que los datos estén en un formato específico. Por lo tanto, saber cómo pivotar los datos eficientemente es una habilidad valiosa al trabajar con R y el tidyverse.
unite()La función unite() de la librería
tidyr en R se utiliza para unir dos o más
columnas en una única columna, generalmente concatenando sus valores en
una cadena de texto. La lógica del comando es la siguiente:
dataframe%>% unite(x, y, z, sep= "arg")%>% head()
X, Y y Z son variables que quieres unir, sep= es el
seperador que utilizarás para separar cada resultado de cada variable
dentro del vector de dato "arg" es el separador, el cual
puede ser " " (un separador) o un guión
("-")
]
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats 1.0.0 ✔ readr 2.1.4
## ✔ ggplot2 3.4.2 ✔ stringr 1.5.0
## ✔ lubridate 1.9.2 ✔ tibble 3.2.1
## ✔ purrr 1.0.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
## # A tibble: 6 × 11
## name fecha hour lat long status category wind pressure
## <chr> <chr> <dbl> <dbl> <dbl> <fct> <dbl> <int> <int>
## 1 Amy 1975-6-27 0 27.5 -79 tropical depression NA 25 1013
## 2 Amy 1975-6-27 6 28.5 -79 tropical depression NA 25 1013
## 3 Amy 1975-6-27 12 29.5 -79 tropical depression NA 25 1013
## 4 Amy 1975-6-27 18 30.5 -79 tropical depression NA 25 1013
## 5 Amy 1975-6-28 0 31.5 -78.8 tropical depression NA 25 1012
## 6 Amy 1975-6-28 6 32.4 -78.7 tropical depression NA 25 1012
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## # hurricane_force_diameter <int>
#Otro ejemplo pero con una fecha distinta:
storms_nueva<-storms %>%
unite(fecha, day, month, year, sep="-") # Esta es la fecha en formato usado en habla hispana. Contrario al primer ejemplo en el que el año está primero.
head(storms_nueva)## # A tibble: 6 × 11
## name fecha hour lat long status category wind pressure
## <chr> <chr> <dbl> <dbl> <dbl> <fct> <dbl> <int> <int>
## 1 Amy 27-6-1975 0 27.5 -79 tropical depression NA 25 1013
## 2 Amy 27-6-1975 6 28.5 -79 tropical depression NA 25 1013
## 3 Amy 27-6-1975 12 29.5 -79 tropical depression NA 25 1013
## 4 Amy 27-6-1975 18 30.5 -79 tropical depression NA 25 1013
## 5 Amy 28-6-1975 0 31.5 -78.8 tropical depression NA 25 1012
## 6 Amy 28-6-1975 6 32.4 -78.7 tropical depression NA 25 1012
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## # hurricane_force_diameter <int>
separate()La función separate() de la librería
tidyr en R hace exactamente lo opuesto a
unite(). Se utiliza para dividir una
columna en varias columnas, basándose en un delimitador
especificado.
df_unido <- data.frame(
nombre = c("Juan", "Ana", "Carlos"),
apellido_completo = c("Gómez Ramírez", "López Sánchez", "Martínez Pérez")
)
print(df_unido)## nombre apellido_completo
## 1 Juan Gómez Ramírez
## 2 Ana López Sánchez
## 3 Carlos Martínez Pérez
df_separado <- df_unido %>%
separate(apellido_completo, into = c("apellido1", "apellido2"), sep = " ")
print(df_separado)## nombre apellido1 apellido2
## 1 Juan Gómez Ramírez
## 2 Ana López Sánchez
## 3 Carlos Martínez Pérez
Recuerdan que habíamos creado una variable llamada fecha en la base de datos original? Lo que haremos es separarla.
## # A tibble: 6 × 13
## name day month year hour lat long status category wind pressure
## <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <fct> <dbl> <int> <int>
## 1 Amy 27 6 1975 0 27.5 -79 tropical de… NA 25 1013
## 2 Amy 27 6 1975 6 28.5 -79 tropical de… NA 25 1013
## 3 Amy 27 6 1975 12 29.5 -79 tropical de… NA 25 1013
## 4 Amy 27 6 1975 18 30.5 -79 tropical de… NA 25 1013
## 5 Amy 28 6 1975 0 31.5 -78.8 tropical de… NA 25 1012
## 6 Amy 28 6 1975 6 32.4 -78.7 tropical de… NA 25 1012
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## # hurricane_force_diameter <int>
Ahora bien, si queremos preservar la variable fecha agregamos el
argumento remove= FALSE:
## # A tibble: 6 × 14
## name fecha day month year hour lat long status category wind pressure
## <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <fct> <dbl> <int> <int>
## 1 Amy 27-6… 27 6 1975 0 27.5 -79 tropi… NA 25 1013
## 2 Amy 27-6… 27 6 1975 6 28.5 -79 tropi… NA 25 1013
## 3 Amy 27-6… 27 6 1975 12 29.5 -79 tropi… NA 25 1013
## 4 Amy 27-6… 27 6 1975 18 30.5 -79 tropi… NA 25 1013
## 5 Amy 28-6… 28 6 1975 0 31.5 -78.8 tropi… NA 25 1012
## 6 Amy 28-6… 28 6 1975 6 32.4 -78.7 tropi… NA 25 1012
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## # hurricane_force_diameter <int>
tidyrEn esta sección, hemos adquirido habilidades sobre cómo fusionar dos conjuntos de datos, generando diferentes tablas basadas en los resultados que buscamos alcanzar. Como observamos, la sintaxis utilizada en todas estas funciones es consistente y comparte similitudes notables con el lenguaje SQL. Estas técnicas de unión son esenciales para manejar datos en R, especialmente cuando trabajamos con conjuntos de datos grandes o múltiples fuentes de datos.
Los diferentes tipos de uniones, como `inner_join`, `left_join`, `right_join` y `full_join`, nos permiten abordar distintos escenarios y cumplir con diferentes requerimientos de análisis de datos. Por ejemplo, `inner_join` nos permite encontrar y combinar las filas que comparten valores comunes en ambas tablas, mientras que `full_join` nos proporciona una unión completa, conservando todas las filas de ambos conjuntos de datos, incluso si no existe una coincidencia directa en las columnas clave.
Estas funciones de unión son herramientas poderosas que, cuando se usan correctamente, pueden simplificar y mejorar nuestros procesos de análisis y manipulación de datos. No solo permiten combinar datos de manera eficiente, sino que también ayudan a mantener la integridad de nuestros datos al preservar las relaciones entre las diferentes variables y observaciones.