Tidyverse
CONAHCYT-Universidad de Guadalajara
8 de enero de 2025
Tidyverse
.R
Existen más de 20 mil funciones escritas por usuarios de R
que están contenidas en paquetes (packages
).
R base
.
R
se almacenan en el Comprehensive R Archive Network (CRAN).R
R
es como un foco 💡CRAN
o algún repositorio en internet (avanzado).R
solo invocando una función: package_name::function()
.Tidyverse
?El
Tidyverse
es una colección de paquetes deR
diseñados para la administración y manipulación de datos ( data science ). Todos los paquetes comparten una misma filosofía de diseño, gramática y una estructura de datos subyacente (tidyverse.org).
Ejercicio 0
en la práctica guiada
Fuente: R 4 Data Science
Tidyverse
palmerpenguins
palmerpenguins
es proveer muchos datos para hacer ejercicios de manipulación, exploración y análisis de datos.?palmerpenguins
.R
R
Fuente: Elaboración propia.
Cuando empiezas a programar para ti mismo:
R
: File>New Project >Existing Directory
.RProj
.Ventajas:
Cada proyecto tiene su propia magia pero yo recomiendo usar la siguiente estructura de directorios:
nombre_proyecto
├── README.md
├── codigo
│ ├── 1_preparacion_datos.Rmd
│ ├── 2_manipulacion_datos.Rmd
│ ├── 3_analisis_datos.Rmd
│ ├── 3_estadistica_descriptiva.Rmd
│ ├── 4_visualizacion.Rmd
│ └── lib_func.R
├── datos
│ ├── originales
│ └── procesados
├── figuras
└── nombre_proyecto.Rproj
README.md
para saber que es lo que hace este proyecto.Podemos generar la estructura de carpetas directamente desde R
:
###########################################################
# Esta función genera una estructura de directorios y
# archivos .Rmd en blanco para comenzar nuestro proyecto.
#
# El único argumento de entrada es el path.
###########################################################
plantilla_proyecto <- function(path) {
# Verificar si el directorio base existe
if (!dir.exists(path)) {
stop(paste("El directorio", path, "no existe."))
}
# Cambiar el directorio de trabajo
setwd(path)
# Nombre del proyecto
nombre_proyecto <- "Proyecto_1"
# Crear carpeta principal del proyecto si no existe
if (!dir.exists(nombre_proyecto)) {
dir.create(nombre_proyecto)
}
# Definir estructura de carpetas (sin acentos)
nombre_subcarpetas <- file.path(nombre_proyecto, c(
"datos", "codigo", "figuras", # Carpetas principales
"datos/original", "datos/procesados" # Subcarpetas
))
# Crear todas las carpetas de manera eficiente
lapply(nombre_subcarpetas, dir.create, recursive = TRUE)
# Crear los archivos dentro de la carpeta "codigo"
carpeta_codigo <- file.path(nombre_proyecto, "codigo")
# Verificar si la carpeta "codigo" existe antes de crear los archivos
if (!dir.exists(carpeta_codigo)) {
stop("La carpeta 'codigo' no existe.")
}
# Definir nombres de los archivos (sin acentos)
file_names <- c(
"1_preparacion_datos", # Preparación de datos
"2_manipulacion_datos", # Combinación de datos
"3_est_descriptiva", # Descriptivos
"3_analisis_datos", # Análisis
"4_visualizacion" # Visualización
)
# Crear las rutas completas para los archivos dentro de "codigo"
file_paths <- file.path(carpeta_codigo, paste0(file_names, ".Rmd"))
# Crear los archivos
file.create(file_paths)
# Crear un archivo adicional para funciones auxiliares
file.create(file.path(carpeta_codigo, "funciones.R"))
message("Estructura del proyecto creada exitosamente.")
}
readr()
Para leer/exportar archivos de texto plano en R
necesitamos:
.
, .``;
o |
.Leer desde archivo | Escribir al archivo | Separador |
---|---|---|
read_delim() |
write_delim() |
Todos. Definido por usuario |
read_csv() |
write_csv() |
Comas |
read_csv2() |
write_csv2() |
Punto y coma |
read_tsv() |
write_tsv() |
Tabulación |
Para importar otros tipos de archivos podemos usar los siguientes paquetes:
readxl
: Archivos en formato MS Excel (Usa Java)haven
: SPSS, Stata y SAS.googlesheets4
: Archivos de Google Sheets.rvtest
: Archivos HTML.R
Leer un archivo ubicado en la misma carpeta que tu script:
Leer un archivo ubicado en una carpeta diferente:
tibbles
en 🌈 Tidyverse
Tidyverse
producen resultados en objetos denominados tibbles
.tibbles
son en escencia similares a los dataframe
pero no son lo mismo:
tibbles
dplyr
El paquete dplyr
provee de una gramática para la manipulación de datos a partir de un conjunto consistente de verbos (funciones):
Verbo (función) | Descripción |
---|---|
filter() |
Seleccionar filas que cumplan una o varias condiciones lógicas |
select() |
Seleccionar o descartar columnas |
rename() |
Cambiar el nombre de una columna |
mutate() |
Transformar valores o crear una nueva columna |
group_by() |
Agrupar datos en una o más columnas |
arrange() |
Ordenar las filas de acuerdo al valor de las variables |
summarize() |
Reduce un grupo de datos a una sola fila |
filter()
Selecciona filas en un dataframe
R base
para hacer algo similar:select()
Seleccionar o descartar columnas en un dataframe
.
mutate()
Transforma valores o crea columnas nuevas.
rename()
La usamos para renombrar columnas existentes.
El símbolo %>%
o |>
(entonces o después) es un componente que encadena todas las operaciones de manipulación de datos.
Ventajas:
# Nombre del objeto que usamos como insumo
imdb_manipulado <- imdb %>%
# Filtramos las películas que duran 132 minutos
filter(duration_minutes == 132) %>%
# Conservamos unicamente el nombre, año y ranking
select(name, year, rank, duration_minutes) %>%
# Creamos una nueva variable (year >=2000)
mutate(siglo21 = ifelse(year >= 2000, 1, 0)) %>%
# Renombramos la variable duration_minutes
rename(duracion_min = duration_minutes)
Notas:
df
solo se menciona una vez al principio (seleccionar y guardar resultados de operaciones).|>
o %>%
.R
Fuente: Allison Horst
Los conjuntos de datos ordenados son fáciles de manipular, modelar y visualizar, y tienen una estructura específica: cada variable es una columna, cada observación es una fila, y cada tipo de unidad de observación es una fila. (Wickham, 2014)
Los datos en formato ancho se caracterizan porque las variables se representan mediante columnas separadas para cada nivel de una variable categórica.
Estudiante | Matemáticas | Ciencias | Historia |
---|---|---|---|
Juan | 90 | 85 | 88 |
Ana | 96 | 100 | 50 |
Pedro | 80 | 75 | 78 |
En la estructura de datos largos cada observación se representa en una fila separada y las variables se colocan en columnas comunes (p.ej. una para el nombre de la materiay otro para el valor de la calificación).
Estudiante | Materia | Calificación |
---|---|---|
Juan | Matemáticas | 90 |
Juan | Ciencias | 85 |
Ana | Matemáticas | 100 |
Ana | Ciencias | 92 |
Pedro | Matemáticas | 86 |
Pedro | Ciencias | 100 |
El paquete tidyr
contiene diversas funciones que pueden ser útiles para ordenar y transformar nuestros datos:
pivot_longer()
: Convierte datos en formato ancho a largo. Es útil cuando necesitamos simplificar nuestros datasets para ejercicios de visualización.
pivot_wider()
: Convierte datos en formato largo a ancho. Es útil cuando queremos hacer tablas o comparaciones entre categorías.
pivot_longer()
cols
: El nombre de las columnas a pivotear de ancho a largo.names_to
: El nombre de la nueva columna que guardará los nombres de las variables pivoteadas.values_to
: El nombre de la nueva columna que contendrá los valores de las variables.values_drop_na
: Descarta los NA
.pivot_longer()
pivot_wider()
datos
: El conjunto de datos a transformar.names_from
: Especifica que valores de las columnas deberán convertirse en los nombres de las columnas en el formato ancho.values_from
: La columna que contiene los valores a rellenar en el formato de columnas anchas.values_fill
: El valor que se asignará a las observaciones perdidas.pivot_wider()
group_by()
Es útil cuando queremos realizar operaciones en algunos grupos dentro de un conjunto de datos.
Sintáxis básica:
df
es un conjunto de datos rectangular.grupo1, grupo2,...
las columnas a partir de las cuales se quieren agrupar los datos.summarize()
Esta función se utiliza para generar resumenes de datos.
Permite calcular estadísticas descriptivas (promedios, sumas, max, min, etc.) sobre un conjunto de datos agrupado.
Sintáxis básica de uso:
df
es un conjunto de datos agrupado con la función group_by()
.estadistica
: El nombre de la columna que contendrá el resumen de los datos.funcion()
: Cálculo que deseas aplicar (p.ej. mean()
, sum()
, max()
, etc.)group_by()
y summarize()
# Datos de ejemplo
datos <- tibble(
categoria = c("A", "A", "B", "B", "C"),
valor = c(10, 20, 30, 40, 50)
)
# Calcular resumen sin agrupar
resumen_general <- datos %>%
summarize(promedio_valor = mean(valor))
# Calcular resumen agrupado
resumen_por_categoria <- datos %>%
group_by(categoria) %>%
summarize(
promedio_valor = mean(valor),
desvest_valor = sd(valor)
)
dplyr
joins
) de datos nos permiten combinar información entre varios conjuntos de datos.R
existen diversos tipos de uniones:
En una unión a la izquierda de dos tablas L
y R
, la tabla resultante (llamemosla LR
) contendrá todos los registros de la tabla L
, pero solo los registros de R
cuyas claves (ID) estén incluidas en L
.
En una unión a la derecha la tabla final contendrá todas las filas de R
, pero sólo aquellas de L
que tengan una clave coincidente. Nótese, que es posible reformular una unión a la derecha de L
con R
como una a la izquierda de R
con L
.
En la unión interna, sólo los registros de L
y R
que tengan una clave igual aparecerán en la tabla final.
En la unión completa, la tabla resultante contendrá todas las filas de L
y todas las de R
, con independencia de que no exista una clave coincidente.
R
{base}Para unir tablas de datos usando R
{base} podemos usar la función merge()
.
df1
y df2
son las tablas de datos que queremos unir.var_id
es la variable en común a partir de la que unimos los datos.merge()
# Ejemplo datos ensayo clínico
demographics <- data.frame(
id = c("P1", "P2", "P3"),
age = c(40, 54, 47),
country = c("GER", "JPN", "BRA"),
stringsAsFactors = FALSE
)
adverse_events <- data.frame(
id = c("P1", "P1", "P3", "P4"),
term = c("Headache", "Neutropenia", "Constipation", "Tachycardia"),
onset_date = c("2020-12-03", "2021-01-03", "2020-11-29", "2021-01-27"),
stringsAsFactors = FALSE
)
merge()
dplyr
left_join()
.right_join()
.inner_join()
.full_join()
.dplyr
En caso de que el nombre de las variables ID de las dos tablas no coincida, tendrás que pasar un vector nombrado como argumento de by
.
Nombre y valor corresponden con la clave en la primera y segunda tabla, respectivamente.