¿Cuál es la evaluación tidy en R? De strings a símbolos guía completa de `sym()`
Si alguna vez has intentado usar el nombre de una columna almacenado en una variable dentro de dplyr y te has topado con errores, este artículo es para ti. La función sym() y la evaluación tidy son conceptos fundamentales que todo analista de datos en R debería dominar.
El Problema: Cuando los Strings No Son Suficientes
Imagina que estás trabajando con datos electorales y quieres calcular el total de votos por partido, pero el nombre del partido está almacenado en una variable:
library(dplyr)
party_name <- "MOVIMIENTO CIUDADANO"
# ❌ Esto NO funciona
datos |>
summarize(partido = sum(party_name))
# Error: no puede sumar un string
# ✅ Esto funciona, pero es inflexible
datos |>
summarize(partido = sum(`MOVIMIENTO CIUDADANO`))
# Funciona, pero ¿qué pasa si el nombre cambia?
El problema es que dplyr necesita trabajar con nombres de columnas (símbolos), no con texto (strings). Aquí es donde entra sym().
¿Qué es sym() y de Dónde Viene?
Origen y Librería
La función sym() pertenece al paquete rlang, el motor que implementa la evaluación tidy (tidy evaluation) en el tidyverse.
# Técnicamente, sym() viene de rlang
library(rlang)
# Pero en la práctica, con dplyr es suficiente
library(dplyr) # Ya incluye rlang automáticamente
No necesitas cargar rlang explícitamente si ya estás usando dplyr, tidyr, o cualquier paquete del tidyverse que dependa de él.
La Solución: sym() + !! (Bang-Bang Operator)
Sintaxis Básica
party_name <- "MOVIMIENTO CIUDADANO"
partido <- datos |>
group_by(id_seccion) |>
summarize(
partido = sum(!!sym(party_name)), # ✅ Funciona perfectamente
nominal = sum(lista_nominal),
total = sum(total_votos)
)
¿Qué Está Pasando Aquí?
Desglosemos el proceso paso a paso:
partido = sum(!!sym(party_name))
party_namecontiene el string"MOVIMIENTO CIUDADANO"sym(party_name)convierte ese string en un símbolo (nombre de columna)!!(bang-bang operator) inyecta ese símbolo en la expresión- Resultado final: Es como si hubieras escrito
sum(\MOVIMIENTO CIUDADANO`)`
Ejemplo Interactivo
# Veamos la transformación paso a paso
party_name <- "MOVIMIENTO CIUDADANO"
# Paso 1: party_name es un string
print(party_name)
# [1] "MOVIMIENTO CIUDADANO"
# Paso 2: sym() lo convierte en símbolo
simbolo <- sym(party_name)
print(simbolo)
# MOVIMIENTO CIUDADANO (sin comillas - es un símbolo)
# Paso 3: !! lo evalúa en el contexto de dplyr
datos |> summarize(total = sum(!!simbolo))
Casos de Uso Comunes
1. Análisis con Múltiples Variables
# Función flexible para analizar cualquier partido
analizar_partido <- function(datos, nombre_partido) {
datos |>
group_by(municipio) |>
summarize(
votos = sum(!!sym(nombre_partido)),
porcentaje = votos / sum(total_votos) * 100
) |>
arrange(desc(votos))
}
# Ahora puedes analizar cualquier partido fácilmente
analizar_partido(datos, "MORENA")
analizar_partido(datos, "PAN")
analizar_partido(datos, "MOVIMIENTO CIUDADANO")
2. Automatización de Reportes
partidos <- c("MORENA", "PAN", "PRI", "MOVIMIENTO CIUDADANO")
# Crear resumen para todos los partidos automáticamente
resultados <- map_df(partidos, function(partido) {
datos |>
summarize(
partido = partido,
total_votos = sum(!!sym(partido)),
porcentaje = (total_votos / sum(total_votos)) * 100
)
})
3. Selección Dinámica de Columnas
# Seleccionar columnas basadas en condiciones
columnas_analizar <- c("votos_2021", "votos_2024")
datos |>
select(municipio, !!!syms(columnas_analizar)) # Nota: syms() para múltiples
Alternativas Modernas: .data[[]]
En versiones recientes de dplyr, existe una alternativa más simple y legible: el operador .data:
party_name <- "MOVIMIENTO CIUDADANO"
# Método tradicional con sym()
datos |>
summarize(partido = sum(!!sym(party_name)))
# Método moderno con .data
datos |>
summarize(partido = sum(.data[[party_name]])) # ✅ Más simple
Comparación de Métodos
| Método | Sintaxis | Ventajas | Cuándo Usar |
|---|---|---|---|
| sym() + !! | !!sym(var) |
Tradicional, bien documentado | Código legacy, casos complejos |
| .data[[]] | .data[[var]] |
Más legible, menos símbolos | Código nuevo, casos simples |
| {{ }} | {{ var }} |
Para parámetros de función | Dentro de funciones personalizadas |
Ejemplo con los Tres Métodos
# 1. Con sym() y !!
mi_funcion_v1 <- function(datos, columna) {
datos |> summarize(total = sum(!!sym(columna)))
}
# 2. Con .data[[]]
mi_funcion_v2 <- function(datos, columna) {
datos |> summarize(total = sum(.data[[columna]]))
}
# 3. Con {{ }} (curly-curly/embrace)
mi_funcion_v3 <- function(datos, columna) {
datos |> summarize(total = sum({{ columna }}))
}
# Los tres funcionan igual
mi_funcion_v1(datos, "MORENA")
mi_funcion_v2(datos, "MORENA")
mi_funcion_v3(datos, MORENA) # Nota: sin comillas con {{ }}
Errores Comunes y Soluciones
Error 1: Olvidar el !!
# ❌ MAL
datos |> summarize(total = sum(sym(party_name)))
# Error: no puede sumar un símbolo sin evaluar
# ✅ BIEN
datos |> summarize(total = sum(!!sym(party_name)))
Error 2: Usar sym() con Nombres Directos
# ❌ INNECESARIO
datos |> summarize(total = sum(!!sym("MORENA")))
# ✅ SIMPLE
datos |> summarize(total = sum(MORENA))
Regla de oro: Solo usa sym() cuando el nombre de la columna está en una variable.
Error 3: Confundir sym() con syms()
columnas <- c("votos_2021", "votos_2024")
# ❌ MAL - sym() es para UNA columna
datos |> select(!!sym(columnas))
# ✅ BIEN - syms() es para MÚLTIPLES columnas
datos |> select(!!!syms(columnas)) # Nota: tres signos !!!
Cuándo Usar Cada Método
Usa sym() + !! cuando:
- Trabajas con código legacy
- Necesitas compatibilidad con versiones antiguas
- Tienes casos de uso muy complejos
Usa .data[[]] cuando:
- Escribes código nuevo
- Quieres máxima legibilidad
- Trabajas con strings simples
Usa {{ }} cuando:
- Creas funciones personalizadas
- Quieres que los usuarios pasen nombres sin comillas
- Necesitas capturar expresiones completas
Ejemplo Práctico Completo: Análisis Electoral
library(dplyr)
# Datos de ejemplo
datos_electorales <- tibble(
seccion = 1:100,
MORENA = sample(100:500, 100),
PAN = sample(100:500, 100),
PRI = sample(100:500, 100),
`MOVIMIENTO CIUDADANO` = sample(50:300, 100)
)
# Función flexible de análisis
analizar_resultados <- function(datos, partido, nivel_agregacion = "total") {
# Método moderno con .data
resumen <- datos |>
summarize(
partido_nombre = partido,
total_votos = sum(.data[[partido]]),
promedio_seccion = mean(.data[[partido]]),
max_seccion = max(.data[[partido]]),
min_seccion = min(.data[[partido]])
)
return(resumen)
}
# Usar la función
analizar_resultados(datos_electorales, "MORENA")
analizar_resultados(datos_electorales, "MOVIMIENTO CIUDADANO")
# Análisis comparativo automático
partidos <- c("MORENA", "PAN", "PRI", "MOVIMIENTO CIUDADANO")
comparativo <- map_df(partidos, ~analizar_resultados(datos_electorales, .x))
print(comparativo)
Resumen Ejecutivo
| Aspecto | Descripción |
|---|---|
| Librería | rlang (incluida automáticamente con dplyr) |
| Propósito | Convertir strings en símbolos para evaluación tidy |
| Sintaxis clásica | !!sym("nombre_columna") |
| Sintaxis moderna | .data[["nombre_columna"]] |
| Cuándo usar | Cuando el nombre de columna está en una variable |
| Alternativa para funciones | {{ variable }} (curly-curly) |
Conclusión
La evaluación tidy y funciones como sym() son herramientas poderosas que hacen que tu código R sea más flexible y reutilizable. Aunque puede parecer complejo al principio, dominar estos conceptos te permitirá crear análisis más dinámicos y automatizados.
Consejo final: Empieza con .data[[]] para casos simples y ve incorporando sym() + !! o {{ }} según tus necesidades específicas crezcan.
¿Has usado evaluación tidy en tus proyectos? ¿Cuál método prefieres? Comparte tu experiencia en los comentarios.

Comentarios
Publicar un comentario