Email efmartinez@icesi.edu.co

Qries eduard-martinez

Qries @emartigo

Qries 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.


1 Introducción a dyplr

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.

1.1 Instalación

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.

2 Exploración inicial de datos

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"

3 Selección y filtrado de datos

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.

3.1 Seleccionar columnas

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

3.2 Filtrar filas

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’
&amp; 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

4 Ordenamiento

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.

5 Creación y modificación de variables

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

6 Resumen y agregación

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.

7 Eliminación de duplicados

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)

8 Renombrar columnas

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)

9 Cambiar formato de tabla

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.

10 Unir conjuntos de datos

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"))

11 Encadenamiento de operaciones

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

12 Práctica

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”.

13 Referencias

  • 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/