https://eduard-martinez.github.io
Hasta este punto, el estudiante ya cuenta con bases en RStudio 🖥️, como la creación de objetos, la exploración de datos y el uso de funciones básicas. Ahora, se introduce la manipulación de datos 🧩, una habilidad clave para transformar y preparar los datasets, antes de avanzar hacia análisis más profundos, modelado o visualización de la información.
Para ello, se trabajará con dplyr, un paquete que forma parte del ecosistema tidyverse. Este ecosistema reúne un conjunto de paquetes diseñados para facilitar la importación, limpieza, manipulación, visualización y modelado de datos. En tidyverse, las funciones de cada paquete siguen una gramática de datos consistente, lo que permite que los análisis sean más intuitivos, legibles y reproducibles. En particular, dplyr proporciona un conjunto de verbos que permiten realizar tareas como seleccionar, filtrar, ordenar, resumir y combinar datos 📊 de manera eficiente y con un código fácil de leer.
dplyr es un paquete que forma parte del ecosistema
tidyverse, y proporciona una gramática potente para la
manipulación de data frames.
Su virtud está en que todas las operaciones se hacen con un conjunto reducido de verbos que trabajan de forma consistente.
¿Cuando usarlo?
Cuando necesite limpiar, transformar o resumir datos antes de analizarlos o visualizarlos.
Cuando busque que tu código sea entendible por otros y fácil de mantener.
Ideal para datos en tibbley
data.frames.
¿Cómo funciona?
Se basa en una gramática de datos: cada verbo corresponde a una operación fundamental.
Favorece un flujo de trabajo lineal y declarativo usando el operador pipe (%>%).
Ejemplo básico:
datos %>%
filter(año == 2024) %>% # Filtra las filas donde la columna `año` sea igual a 2024
select(nombre, ventas) %>% # Conserva únicamente las variables `nombre` y `ventas`.
arrange(desc(ventas)) # Ordena las filas de mayor a menor.
💡Un pipe conecta pasos como si fueran una receta. Esto facilita leer el código como una secuencia de instrucciones.
Antes de empezar a trabajar con dplyr, el estudiante debe instalar el paquete.
Instalación directa de dplyr
install.packages("dplyr")
library(dplyr)
Instalación dentro de tidyverse
El paquete tidyverse es una colección de paquetes diseñados para la ciencia de datos en R. Incluye dplyr junto con otros muy útiles como ggplot2, readr, tidyr, tibble, entre otros.
Si el estudiante prefiere tener todo el ecosistema tidyverse listo, puedes instalarlo así:
install.packages("tidyverse")
library(tidyverse)
En este capítulo se usa la base de datos ventas, que corresponde a un conjunto de datos simulado con fines académicos.
Algunas de las variables que usted puede encontrar son:
id_producto: Identificador numérico único asignado a
cada producto.
producto: Nombre del producto registrado en el
inventario.
categoria: Clasificación general del producto (por
ejemplo, Electrónica, Hogar).
precio: Valor unitario del producto.
cantidad: Número de unidades disponibles del
producto.
fecha: Fecha de registro del producto en el
inventario.
Para explorar un dataset, use alguna de las funciones que se proponen a continuación. Recuerde, que familiarizarse con los datos antes de manipularlos, es importante para identificar problemas, inconsistencias o patrones iniciales que guiarán el análisis
glimpse(): visión general con tipos de datos y primeras
observaciones.summary(): estadísticos básicos por columna.head(), tail(): primeras o últimas
filas.names() o colnames(): nombres de
columnas.as_tibble(): convierte a tibble.💡 Piensa en un tibble como la versión moderna del data.frame: ideal en el tidyverse y para evitar que R cambie tipos de datos sin avisar. Si el estudiante quiere explorar más sobre Tibbles puede visitar la documentación oficial
glimpse(ventas)
## Rows: 30
## Columns: 6
## $ id_producto <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, …
## $ producto <chr> "Laptop", "Mouse", "Escritorio", "Silla", "Teclado", "Moni…
## $ categoria <chr> "Electronica", "Electronica", "Hogar", "Hogar", "Electroni…
## $ precio <int> 3500, 50, 200, 150, 70, 500, 45, 300, 120, 800, 3500, 50, …
## $ cantidad <int> 2, 10, 5, 8, 7, 3, 15, 4, 6, 5, 2, 10, 5, 8, 7, 3, 15, 4, …
## $ fecha <IDate> 2025-01-10, 2025-01-13, 2025-01-16, 2025-01-19, 2025-01-…
summary(ventas)
## id_producto producto categoria precio
## Min. : 1.0 Length:30 Length:30 Min. : 45.0
## 1st Qu.: 3.0 Class :character Class :character 1st Qu.: 70.0
## Median : 5.5 Mode :character Mode :character Median : 175.0
## Mean : 5.5 Mean : 573.5
## 3rd Qu.: 8.0 3rd Qu.: 500.0
## Max. :10.0 Max. :3500.0
## cantidad fecha
## Min. : 2.0 Min. :2025-01-10
## 1st Qu.: 4.0 1st Qu.:2025-01-31
## Median : 5.5 Median :2025-02-22
## Mean : 6.5 Mean :2025-02-22
## 3rd Qu.: 8.0 3rd Qu.:2025-03-16
## Max. :15.0 Max. :2025-04-07
names(ventas)
## [1] "id_producto" "producto" "categoria" "precio" "cantidad"
## [6] "fecha"
Para seleccionar columnas, use select(), también puede
usar : para un rango de columnas. Para filtrar filas según
condiciones, use filter(), indicando la condición que deben
cumplir las observaciones. Esta tarea le permite centrarse solo en la
información relevante y evita que registros innecesarios compliquen su
análisis.
Esta operación implica seleccionar un conjunto de variables (columnas) dentro del dataset.
select(): Elegir columnas específicas por nombre,
patrón o posición.
Tambíen la función select() permite elegir columnas
de un data frame/tibble utilizando patrones.
| Helper | Descripción | Ejemplo |
|---|---|---|
starts_with()
|
Selecciona columnas que comienzan con el patrón específico. | select(starts_with(‘id’)) |
ends_with()
|
Selecciona columnas que terminan con el patrón específico. | select(ends_with(‘to’)) # ej: producto |
contains()
|
Selecciona columnas que contienen el patrón en cualquier parte del nombre. | select(contains(‘cat’)) # ej: categoria |
everything()
|
Selecciona todas las columnas, útil para reordenar. | select(producto, everything()) |
last_col()
|
Selecciona la última columna. | select(last_col()) → fecha |
all_of()
|
Selecciona columnas especificadas en un vector (lanza error si alguna no existe). | select(all_of(c(‘producto’,‘precio’))) |
any_of()
|
Igual que all_of(), pero ignora los nombres que no existen (no lanza error). | select(any_of(c(‘producto’,‘descuento’))) |
Ejemplos
1.Elegir columnas por nombre
ventas %>% select(producto, precio, cantidad) %>%
head(5)
## producto precio cantidad
## 1 Laptop 3500 2
## 2 Mouse 50 10
## 3 Escritorio 200 5
## 4 Silla 150 8
## 5 Teclado 70 7
2.Elegir columnas por patrón
ventas %>% select(starts_with("precio")) %>%
head(5)
## precio
## 1 3500
## 2 50
## 3 200
## 4 150
## 5 70
Esta operación implica filtrar las observaciones (filas) que satisfacen los criterios establecidos.
filter(): Extraer filas que cumplen condiciones
lógicas.
Con filter() puede aplicar múltiples condiciones al
mismo tiempo.
Al aplicar la función filter(), es posible complementar
el filtrado con distintos operadores lógicos.
| Operador | Descripción | Ejemplo |
|---|---|---|
| < , > | Menor y mayor que | ventas > 100 |
| <= , >= | Menor o igual y mayor o igual que | precio <= 50 |
==
|
Igual a | categoria == ‘Hogar’ |
!=
|
Diferente de | categoria != ‘Electrónica’ |
&
|
y (AND lógico) | ventas > 100 & categoria == ‘Hogar’ |
|
|
o (OR lógico) | categoria == ‘Hogar’ | categoria == ‘Moda’ |
!
|
Negación lógica | !(categoria == ‘Hogar’) |
between()
|
Dentro de un rango | between(precio, 50, 100) |
%in%
|
Pertenece a un conjunto de valores | categoria %in% c(‘Hogar’,‘Moda’) |
Ejemplos combinando operadores lógicos:
1. Filtra únicamente las filas donde precio es mayor a 100 y la categoría es “Hogar”.
ventas %>%
filter(precio > 100 & categoria == "Hogar") %>%
head(5)
## id_producto producto categoria precio cantidad fecha
## 1 3 Escritorio Hogar 200 5 2025-01-16
## 2 4 Silla Hogar 150 8 2025-01-19
## 3 9 Cafetera Hogar 120 6 2025-02-03
## 4 3 Escritorio Hogar 200 5 2025-02-15
## 5 4 Silla Hogar 150 8 2025-02-18
2. Devuelve las filas donde la columna producto es igual a “Mouse” o “Cafetera”
ventas %>% filter(producto %in% c("Mouse","Cafetera"))%>%
head(5)
## id_producto producto categoria precio cantidad fecha
## 1 2 Mouse Electronica 50 10 2025-01-13
## 2 9 Cafetera Hogar 120 6 2025-02-03
## 3 2 Mouse Electronica 50 10 2025-02-12
## 4 9 Cafetera Hogar 120 6 2025-03-05
## 5 2 Mouse Electronica 50 10 2025-03-14
3. Devuelve las filas que no pertenecen a la categoría “Hogar” con precio menor a 100
ventas %>% filter(!(categoria == "Hogar" & precio < 100)) %>%
head(5)
## id_producto producto categoria precio cantidad fecha
## 1 1 Laptop Electronica 3500 2 2025-01-10
## 2 2 Mouse Electronica 50 10 2025-01-13
## 3 3 Escritorio Hogar 200 5 2025-01-16
## 4 4 Silla Hogar 150 8 2025-01-19
## 5 5 Teclado Electronica 70 7 2025-01-22
Para ordenar los datos, use arrange(). Para un orden
descendente, envuelva la variable con desc(). Ordenar los
datos facilita la identificación de patrones, la comparación entre
registros y la detección de posibles errores, mejorando la claridad del
análisis.
arrange: Ordena filas por una o varias
columnas.
Cuándo: antes de reportar resultados o aplicar funciones que dependen del orden.
# Ordena el dataframe de mayor a menor según la columna 'precio'
ventas %>% arrange(desc(precio)) %>% head(5)
## id_producto producto categoria precio cantidad fecha
## 1 1 Laptop Electronica 3500 2 2025-01-10
## 2 1 Laptop Electronica 3500 2 2025-02-09
## 3 1 Laptop Electronica 3500 2 2025-03-11
## 4 10 Tablet Electronica 800 5 2025-02-06
## 5 10 Tablet Electronica 800 5 2025-03-08
⚠️ Si su dataset es muy grande, evita ordenar si no es necesario — puede ser costoso en tiempo.
Crear o modificar variables enriquece el análisis y permite responder preguntas que los datos originales no revelan.
mutate(): agrega o transforma columnas conservando las
existentes.Con mutate() el estudiante puede realizar distintas
operaciones con las variables de un data frame como:
Crear nuevas columnas a partir de operaciones aritméticas (suma, resta, multiplicación, división).
Transformar variables existentes, aplicando funciones como log(), round(), toupper(), etc.
Generar variables condicionales con funciones como if_else() o case_when().
Trabajar con fechas y tiempos, por ejemplo usando lubridate.
Aplicar funciones sobre varias columnas al mismo tiempo, usando across().
data <- ventas %>%
mutate(
# Crea una nueva columna "total" multiplicando precio * cantidad
total = precio * cantidad,
# Crea una columna categórica "nivel_venta" usando condiciones
nivel_venta = case_when(
total >= 3000 ~ "Alta",
total >= 1000 & total < 3000 ~ "Media",
TRUE ~ "Baja"
)
)
data %>% head(5)
## id_producto producto categoria precio cantidad fecha total
## 1 1 Laptop Electronica 3500 2 2025-01-10 7000
## 2 2 Mouse Electronica 50 10 2025-01-13 500
## 3 3 Escritorio Hogar 200 5 2025-01-16 1000
## 4 4 Silla Hogar 150 8 2025-01-19 1200
## 5 5 Teclado Electronica 70 7 2025-01-22 490
## nivel_venta
## 1 Alta
## 2 Baja
## 3 Media
## 4 Media
## 5 Baja
Para resumir o agregar información, use summarise()
junto con group_by(). Primero se agrupan las observaciones
según una o más variables, y luego se calculan estadísticas como
promedios o totales. Esto es importante porque condensa grandes
volúmenes de datos y permite extraer insights clave de manera rápida y
organizada.
group_by(): crea agrupaciones (por una o más
variables).
summarise(): calcula estadísticas sobre esas
agrupaciones.
ventas %>%
group_by(categoria) %>% # agrupa los datos por cada `categoría`
summarise(
total_productos = n(), # cuenta de registros
ventas_totales = sum(precio * cantidad), # suma total de ventas
promedio_precio = mean(precio), # precio promedio
max_precio = max(precio), # precio máximo
min_precio = min(precio) # precio mínimo
) %>% ungroup()
## # A tibble: 2 × 6
## categoria total_productos ventas_totales promedio_precio max_precio min_precio
## <chr> <int> <int> <dbl> <int> <int>
## 1 Electron… 18 44070 870 3500 50
## 2 Hogar 12 10785 129. 200 45
⚠️ Se recomienda usar ungroup()después de un group_by(),
para regresar a la estructura de los datos inicial.
La función distinct() permite identificar y extraer
filas únicas o combinaciones específicas de valores en determinadas
columnas.
distinct(): Sirve cuando un mismo cliente, producto
o transacción aparece repetido en la tabla.
Permite especificar la(s) columna(s) que se usan como criterio de unicidad.
Con el argumento .keep_all = TRUE se mantienen todas
las demás columnas asociadas.
ej <- ventas %>%
distinct(id_producto, .keep_all = TRUE) %>% # Conserva solo una fila por cada valor único de `id_producto`
head(5)
Para cambiar el nombre de columnas, use rename().
Considere renombrar columnas para facilitar la comprensión del dataset y
mejorar la legibilidad del código.
rename(nuevo_nombre = viejo_nombre): cambia nombres
específicos.
rename_with(): transforma todos los nombres con una
función (ej: tolower() para minúsculas, toupper() para
mayúsculas).
# Cambiar nombre de la columna "fecha" a "fecha_venta"
ventas <- ventas %>%
rename(fecha_venta = fecha)
# Pasar todos los nombres de columnas a minúsculas
ventas <- ventas %>%
rename_with(tolower)
En análisis y visualización, a veces se necesita pasar de formato
ancho (wide) a formato largo (long) o viceversa. Para pasar de ancho a
largo se usa pivot_longer(), indicando las columnas que se
quieren transformar en filas y los nombres para las nuevas variables.
Para el proceso inverso, de largo a ancho, se utiliza
pivot_wider().
pivot_longer(): convierte varias columnas en
filas.
pivot_wider(): hace lo contrario, expande filas en
columnas.
ventas_long <- ventas %>%
pivot_longer(
cols = c(precio, cantidad), # columnas a transformar
names_to = "variable", # nombres de columnas van aquí
values_to = "valor" # valores van aquí
)
ventas_long %>% head(5)
## # A tibble: 5 × 6
## id_producto producto categoria fecha_venta variable valor
## <int> <chr> <chr> <IDate> <chr> <int>
## 1 1 Laptop Electronica 2025-01-10 precio 3500
## 2 1 Laptop Electronica 2025-01-10 cantidad 2
## 3 2 Mouse Electronica 2025-01-13 precio 50
## 4 2 Mouse Electronica 2025-01-13 cantidad 10
## 5 3 Escritorio Hogar 2025-01-16 precio 200
Ahora con esta disposición de la tabla, se podría graficar la evolución de precios vs. cantidades.
Para unir datasets, use left_join(), inner_join() o alguna de las funciones que se muestran en la siguiente tabala. El primer argumento es el dataset principal, el segundo el dataset a unir, y by indica la(s) columna(s) que relacionan ambos.
Puede adicionar variables a un conjunto de datos usando la familia de
funciones de join():
| Función | Descripción | Ejemplo |
|---|---|---|
inner_join()
|
Devuelve únicamente las filas que tienen coincidencia en ambas tablas. | inner_join(clientes, ventas, by = ‘id’) |
full_join()
|
Combina todas las filas de ambas tablas, rellenando con NA donde no existan coincidencias. | full_join(clientes, ventas, by = ‘id’) |
left_join()
|
Mantiene todas las filas de la tabla izquierda y añade datos coincidentes de la derecha (con NA si no hay coincidencia). | left_join(clientes, ventas, by = ‘id’) |
right_join()
|
Mantiene todas las filas de la tabla derecha y añade datos coincidentes de la izquierda (con NA si no hay coincidencia). | right_join(clientes, ventas, by = ‘id’) |
anti_join()
|
Devuelve las filas de la izquierda que no tienen coincidencia en la derecha. | anti_join(clientes, ventas, by = ‘id’) |
Fuente: Imaobong Njokko.
Conjuntos de datos para hacer la aplicación:
Dataset 1:
## # A tibble: 4 × 3
## Casa Visita Sexo
## <dbl> <dbl> <chr>
## 1 101 2 Mujer
## 2 201 1 Mujer
## 3 201 2 Hombre
## 4 301 1 Hombre
Dataset 2:
data_2 <- tibble(Casa=c(101,101,201,201),
Visita=c(1,2,1,2),
Edad=c(23,35,7,24),
Ingresos=c(500000,1000000,NA,2000000)) %>% print()
## # A tibble: 4 × 4
## Casa Visita Edad Ingresos
## <dbl> <dbl> <dbl> <dbl>
## 1 101 1 23 500000
## 2 101 2 35 1000000
## 3 201 1 7 NA
## 4 201 2 24 2000000
Ejemplo: left_join():
ventas <- left_join(x=data_1,y=data_2,by=c("Casa","Visita"))
Ejemplo: right_join():
ventas <- right_join(x=data_1,y=data_2,by=c("Casa","Visita"))
Ejemplo: inner_join():
ventas <- inner_join(x=data_1,y=data_2,by=c("Casa","Visita"))
Ejemplo: full_join():
ventas <- full_join(x=data_1,y=data_2,by=c("Casa","Visita"))
El encadenamiento de operaciones permite construir pipelines
que muestran de manera clara y ordenada la transformación de los datos.
Al inicio de esta guía se mencionó el uso del pipe
(%>%), y a lo largo de los ejemplos usted ha podido
observar este símbolo en la mayoría de los códigos.
El pipe tiene como propósito conectar una instrucción con la siguiente, de modo que la salida de una operación se convierte en la entrada de la siguiente. Esto genera un flujo de trabajo lineal, fácil de leer y de seguir de arriba hacia abajo, en lugar de depender de múltiples objetos intermedios o de llamadas anidadas que dificultan la comprensión.
ventas %>%
# 1. Convertir fecha a tipo Date (si aún no lo está)
mutate(fecha = as.Date(fecha_venta)) %>%
# 2. Extraer el mes con base R
mutate(mes = format(fecha_venta, "%m")) %>%
# 3. Calcular el valor total de cada venta (precio * cantidad)
mutate(valor_total = precio * cantidad) %>%
# 4. Filtrar solo productos de la categoría "Electronica"
filter(categoria == "Electronica") %>%
# 5. Agrupar por producto y mes
group_by(producto, mes) %>%
# 6. Resumir el total vendido y el número de transacciones
summarise(
ventas_totales = sum(valor_total, na.rm = TRUE),
transacciones = n(),
.groups = "drop"
) %>%
# 7. Ordenar por las ventas totales de mayor a menor
arrange(desc(ventas_totales)) %>%
head(7)
## # A tibble: 7 × 4
## producto mes ventas_totales transacciones
## <chr> <chr> <int> <int>
## 1 Laptop 01 7000 1
## 2 Laptop 02 7000 1
## 3 Laptop 03 7000 1
## 4 Tablet 02 4000 1
## 5 Tablet 03 4000 1
## 6 Tablet 04 4000 1
## 7 Monitor 01 1500 1
Descargue aquí una base de datos sobre el Registro Mercantil de empresas de la ciudad de Cali. Realice las siguientes tareas:
Filtrado y selección
Obtenga las empresas del departamento VALLE que tengan activos mayores a 50,000 millones y que se hayan renovado en el año 2023.
Filtre todas las empresas cuya razón social contenga la palabra “RESTAURANTE” o “CAFETERIA”.
Creación de variables con
Crea una nueva columna llamada liquidez = Activos M. - Pasivos M..
Clasifique las empresas en categorías de tamaño según sus ingresos:
“Pequeña” si Ingresos M. < 5,000
“Mediana” si está entre 5,000 y 50,000
“Grande” si es ≥ 50,000
Agrupamiento y resúmenes
Agrupe las empresas según si en la columna
razon_social aparece la palabra “TIENDA”, y cuente cuántas
empresas pertenecen a esta categoría frente a las demás.
Agrupe las empresas por su código CIIU y obtenga un resumen económico de cada sector. Utilice el CIIU1. En el siguiente link puede consultar la Clasificación de Actividades Económicas en Colombia.
Ordenamiento con
Ordene las empresas por activos en orden descendente.
Ordene primero por departamento, y dentro de cada departamento, por ingresos de mayor a menor.
Reestructuración de datos
Renombre la columna “Ingresos M.” como ingresos_millones.
Convierta las columnas Activos M., Ingresos M., Pasivos M., Patrimonio M. a formato largo (pivot_longer) con los nombres “variable” y “valor”.
Wickham, H., François, R., Henry, L., & Müller, K. (2023). dplyr: A Grammar of Data Manipulation. R package version 1.1.4. Disponible en: https://CRAN.R-project.org/package=dplyr
Wickham, H., & Grolemund, G. (2017). R for Data Science: Import, Tidy, Transform, Visualize, and Model Data. O’Reilly Media. Disponible en línea: https://r4ds.hadley.nz/