Canalización de limpieza de datos con R dplyr: de datos crudos a tablas limpias
Problema
Las personas analistas pierden tiempo escribiendo bucles repetitivos en R para limpiar conjuntos de datos. El resultado son scripts frágiles, columnas inconsistentes e iteraciones lentas cada vez que llega un nuevo archivo.
Agravar
Los pasos manuales se acumulan: seleccionar columnas incorrectas, aplicar transformaciones en el orden equivocado o olvidar manejar factores frente a caracteres. Cada error obliga a re‑ejecutar el flujo y aumenta el riesgo de enviar métricas incorrectas a los paneles de control posteriores.
Solución
Adopta una canalización consistente con dplyr que refleje la lógica de SQL y mantenga cada transformación legible. Los verbos siguientes cubren selección de columnas, filtrado de filas, creación de nuevas variables, resúmenes, ordenamiento y joins seguros para que los datos queden ordenados antes del modelado o la visualización.
Canalización básica en acción
library(dplyr)
clean_sales <- raw_sales %>%
mutate(
region = as.character(region), # avoid accidental factor levels
revenue = price * quantity
) %>%
filter(!is.na(revenue), revenue > 0) %>%
select(order_id, region, revenue, channel, order_date) %>%
arrange(desc(revenue)) %>%
group_by(region, channel) %>%
summarise(
orders = n(),
revenue = sum(revenue),
avg_order = mean(revenue),
.groups = "drop"
)Verbos de dplyr y sus equivalentes en SQL
| dplyr verb | Propósito | Analogía en SQL | Nota rápida |
|---|---|---|---|
select() | conservar o renombrar columnas | SELECT col1, col2 | Usa everything() para reordenar rápidamente. |
filter() | subconjuntos de filas | WHERE condition | Combínalo con %in% para múltiples valores. |
mutate() | agregar/transformar columnas | SELECT col1, col2*2 AS col2x | Prefiere if_else() para lógica con tipos estables. |
summarise() + group_by() | métricas agrupadas | GROUP BY ... | Agrega .groups = "drop" para desagrupar. |
arrange() | ordenar filas | ORDER BY | Usa desc() para orden descendente. |
left_join() | enriquecer con tablas de referencia | LEFT JOIN | Mantén las claves de join del mismo tipo (character vs factor). |
bind_rows() / bind_cols() | apilar o ensanchar tablas | UNION ALL / concatenación de columnas | Asegura esquemas compatibles al apilar. |
Joins vs. binds de un vistazo
# Join: add columns from a lookup table
sales_with_regions <- sales %>%
left_join(region_lookup, by = "region_id")
# Bind: stack identical schemas
all_sales <- bind_rows(sales_2023, sales_2024)Evitar problemas con factors y codificación
- Convierte identificadores a
characterantes de hacer joins para evitar niveles no coincidentes. - Usa
mutate(across(where(is.factor), as.character))si un CSV se leyó con factors implícitos. - Estandariza texto con
stringr::str_trimytolowerantes de agrupar para evitar categorías duplicadas.
Plantilla rápida de inicio
prep_data <- function(df) {
df %>%
mutate(across(where(is.factor), as.character)) %>%
filter(!is.na(key_id)) %>%
distinct() %>%
select(key_id, everything())
}Lista de verificación antes de guardar
- Las columnas están explícitamente seleccionadas y ordenadas.
- Los joins clave usan tipos coincidentes y sufijos claros cuando es necesario (
suffix = c(".src", ".lkp")). - Los resúmenes eliminan el agrupamiento para evitar sorpresas en pasos posteriores.
- Las salidas contienen solo columnas limpias y legibles para personas, listas para gráficos o modelos.
Guías relacionadas
- Construye tablas ordenadas desde cero: Creating Dataframe in R
- Agrupa datos para resúmenes: Grouping in R with group_by()
- Prepara datos para gráficos: R ggplot2 Quickstart