Cómo usar esta guía y preparar tu entorno
Esta página está pensada como un curso de consulta, no como una colección de definiciones. Lee cada concepto, copia el ejemplo en RStudio y cambia al menos un valor para comprobar qué ocurre. Si aparece un error, léelo con calma, localiza la línea y compárala con el ejemplo: depurar es parte normal del aprendizaje.
Durante la primera lectura conviene seguir el orden. En las siguientes puedes usar el menú lateral, el menú superior o los enlaces para volver al inicio; todo está dentro de esta misma página, así que no dependes de subpáginas que puedan romperse al subirla a Cloudflare Pages.
Qué necesitas instalar
- R: lenguaje que ejecuta las instrucciones.
- RStudio Desktop: editor, consola, gráficos, archivos y ayuda en una sola interfaz.
- Paquetes: extensiones que añaden funciones; aquí se usa especialmente
tidyverse.
install.packages("tidyverse")
library(tidyverse)
# Comprueba que la instalación funcionó
tibble(nombre = c("Ana", "Luis"), puntos = c(8, 10))En RStudio, crea un proyecto antes de empezar. Así las rutas relativas se mantienen estables y puedes mover la carpeta completa sin cambiar cada ruta del código.
1. Fundamentos: cómo piensa R
R es un lenguaje orientado al análisis estadístico, la visualización y la automatización. En vez de depender de una secuencia de clics, describes una transformación: recibes datos, los filtras, calculas columnas, resumes y presentas el resultado. La ventaja aparece cuando llega un archivo nuevo: puedes repetir el procedimiento y auditarlo.
La consola ejecuta expresiones. Una expresión puede ser un número, una operación, una comparación o una función. El resultado se muestra si no lo guardas; se conserva en un objeto cuando usas el operador de asignación.
2 + 2
precio <- 125
precio * 1.16
mensaje <- "Hola, R"
mensajeComentarios, nombres y orden
Los comentarios empiezan con #. Usa nombres descriptivos y consistentes: ventas_enero comunica más que x. Evita cambiar el mismo objeto muchas veces sin necesidad; conservar objetos como raw, limpio y resumen hace visible el proceso.
# Ventas de enero en pesos
ventas_enero <- c(1200, 980, 1450, 1100)
ingreso_total <- sum(ventas_enero)
ingreso_promedio <- mean(ventas_enero)
c(total = ingreso_total, promedio = ingreso_promedio)Errores iniciales frecuentes
- Comillas curvas en vez de comillas normales.
- Coma decimal en un número: escribe
12.5. - Paréntesis, comillas o llaves sin cerrar.
- Confundir un nombre como
Ventasconventas; R distingue mayúsculas y minúsculas.
2. Objetos, tipos y estructuras
R distingue entre números, texto, valores lógicos, fechas y ausentes. Esa diferencia importa: sumar un número y concatenar un texto no son la misma operación. Antes de analizar una tabla, inspecciona su estructura y confirma que cada columna tenga el tipo esperado.
| Tipo | Ejemplo | Uso |
|---|---|---|
| Numérico | 12.5 | Precios, cantidades y mediciones. |
| Carácter | "México" | Nombres, categorías y códigos. |
| Lógico | TRUE | Filtros y condiciones. |
| Fecha | as.Date("2026-08-14") | Orden temporal y periodos. |
| Ausente | NA | Dato desconocido o no registrado. |
Vectores y factores
Un vector guarda valores del mismo tipo. El índice empieza en 1. Un factor representa categorías y mantiene niveles, algo importante al ordenar, graficar o modelar.
ciudades <- c("CDMX", "Puebla", "Mérida")
ventas <- c(100, 140, 90)
ventas[2]
ventas[ventas > 100]
nivel <- factor(c("bajo", "alto", "medio", "alto"))
levels(nivel)Listas, tibbles y tablas
Una lista puede guardar elementos de tipos distintos. Un data.frame organiza columnas relacionadas en filas; un tibble, incluido en tidyverse, ofrece una impresión compacta y conserva mejor la información al trabajar en la consola.
persona <- list(nombre = "Ana", edad = 31, activo = TRUE)
clientes <- tibble(
id = 1:4,
nombre = c("Ana", "Luis", "Mara", "Omar"),
compras = c(3, 1, 5, 2),
gasto = c(850, 120, 1320, 410)
)
str(clientes)
summary(clientes)str(), head(), nrow(), names() y summary() antes de sacar conclusiones.3. Vectores, índices y condiciones
Una condición produce TRUE o FALSE para cada valor. Esa máscara se usa para seleccionar datos. El patrón es poderoso porque expresa la pregunta directamente: “conservar edades mayores o iguales a 18”.
edades <- c(17, 24, 35, 42, 29)
edades[edades >= 18]
edades[edades >= 18 & edades < 40]
productos <- c("libro", "curso", "libro", "licencia")
productos[productos == "libro"]Operadores indispensables
==igualdad y!=distinto.>,>=,<,<=comparaciones.&“y”,|“o” y!negación.%in%pertenencia a una lista de valores.
estado <- c("pagado", "pendiente", "cancelado", "pagado")
validos <- c("pagado", "pendiente")
estado %in% validosValores faltantes y orden
Las comparaciones con valores ausentes pueden devolver NA. Usa is.na() y decide si excluir, marcar o corregir los faltantes. No conviertas automáticamente un dato desconocido en cero.
calificaciones <- c(8, 9, NA, 7, 10)
sum(is.na(calificaciones))
mean(calificaciones, na.rm = TRUE)
calificaciones[!is.na(calificaciones)]Para ordenar una tabla completa, ordena la tabla, no solo un vector aislado, de modo que las columnas sigan correspondiendo a la misma fila.
clientes %>% arrange(desc(gasto))
clientes %>% arrange(compras, desc(gasto))4. Funciones, condiciones y control
Una función recibe entradas, hace una operación y devuelve una salida. Crear funciones pequeñas convierte una regla repetida en una pieza que puedes probar y reutilizar. Usa argumentos con nombres claros y valida entradas cuando una respuesta incorrecta sería costosa.
calcular_total <- function(precio, cantidad, impuesto = 0.16) {
subtotal <- precio * cantidad
subtotal * (1 + impuesto)
}
calcular_total(250, 3)
calcular_total(250, 3, impuesto = 0.08)Decisiones y valores límite
clasificar_gasto <- function(monto) {
if (monto < 0) return("revisar: monto negativo")
if (monto >= 1000) return("alto")
if (monto >= 300) return("medio")
"bajo"
}
clasificar_gasto(1250)
clasificar_gasto(40)Bucles y alternativas
Los bucles son útiles para tareas secuenciales, pero muchas transformaciones tabulares pueden expresarse de manera vectorizada.
resultados <- numeric(4)
for (i in 1:4) {
resultados[i] <- i^2
}
resultados
sapply(1:4, function(i) i^2)5. Tablas: seleccionar, transformar, agrupar y unir
El flujo tabular más habitual puede resumirse en cinco verbos: seleccionar columnas, filtrar filas, crear variables, agrupar y resumir. El pipe permite leer la transformación de izquierda a derecha.
ventas <- tibble(
fecha = as.Date(c("2026-01-03", "2026-01-04", "2026-01-04", "2026-01-08")),
ciudad = c("CDMX", "Puebla", "CDMX", "Mérida"),
producto = c("A", "A", "B", "B"),
unidades = c(2, 3, 1, 5),
precio = c(150, 150, 240, 240)
)
ventas %>%
mutate(total = unidades * precio) %>%
filter(total >= 300) %>%
select(fecha, ciudad, producto, total)Resumen por grupo
resumen_ciudad <- ventas %>%
mutate(total = unidades * precio) %>%
group_by(ciudad) %>%
summarise(
pedidos = n(),
unidades = sum(unidades),
ingresos = sum(total),
ticket_promedio = mean(total),
.groups = "drop"
) %>%
arrange(desc(ingresos))Unir catálogos
Cuando una tabla contiene códigos y otra atributos, usa una unión. La clave debe identificar correctamente cada registro. Revisa duplicados antes y compara las filas después de unir.
catalogo <- tibble(
producto = c("A", "B"),
categoria = c("material", "servicio")
)
ventas %>% left_join(catalogo, by = "producto")join suele indicar claves duplicadas.6. Importar, limpiar y validar datos reales
Los datos reales contienen espacios, acentos inconsistentes, fechas ambiguas, valores como “N/D”, duplicados y columnas que mezclan números con texto. Limpiar no es maquillar: es establecer qué observaciones son comparables y qué supuestos tendrá tu análisis.
Importar un CSV
library(readr)
raw <- read_csv("datos/ventas.csv", show_col_types = FALSE)
names(raw)
glimpse(raw)Normalizar nombres y categorías
library(dplyr)
library(stringr)
ventas_limpias <- raw %>%
rename(fecha = Fecha, ciudad = Ciudad, total = Importe) %>%
mutate(
ciudad = str_squish(str_to_title(ciudad)),
total = parse_number(as.character(total)),
fecha = as.Date(fecha, format = "%d/%m/%Y")
)Faltantes, duplicados y rangos
ventas_limpias %>% summarise(
filas = n(),
fechas_vacias = sum(is.na(fecha)),
ciudades_vacias = sum(is.na(ciudad)),
totales_vacios = sum(is.na(total)),
duplicados = n() - n_distinct(fecha, ciudad, total)
)
ventas_limpias %>% filter(is.na(total) | total < 0)No existe una solución universal para un faltante. Puedes excluirlo, imputarlo, marcarlo o regresar a la fuente. Declara qué hiciste y cuánto cambió la muestra.
raw y crea objetos sucesivos como ventas_limpias y ventas_modelo. No destruyas la evidencia original.7. Gráficos con ggplot2
Un gráfico debe responder una pregunta. Define si quieres comparar categorías, mostrar evolución temporal, explorar una relación o conocer una distribución. ggplot2 construye el resultado por capas: datos, estéticas, geometrías, escalas y tema.
library(ggplot2)
ventas %>%
mutate(total = unidades * precio) %>%
ggplot(aes(x = ciudad, y = total, fill = ciudad)) +
geom_col() +
labs(title = "Ingresos por ciudad", x = NULL, y = "Ingresos") +
theme_minimal() +
theme(legend.position = "none")Barras
Compara categorías. Ordena de mayor a menor si la lista es larga.
geom_col()Líneas
Muestra evolución temporal y cambios entre fechas.
geom_line()Puntos
Explora relación entre dos variables numéricas.
geom_point()Histograma
Observa la distribución y concentración de una variable.
geom_histogram()Ejemplo de serie temporal
ventas %>%
mutate(total = unidades * precio) %>%
group_by(fecha) %>%
summarise(ingresos = sum(total), .groups = "drop") %>%
ggplot(aes(fecha, ingresos)) +
geom_line(linewidth = 1.2, color = "#087f8c") +
geom_point(size = 3, color = "#df9e32") +
labs(title = "Ingresos diarios", x = NULL, y = "Pesos") +
theme_minimal()8. Resumir, comparar y comunicar
Un promedio aislado puede ocultar diferencias. Acompáñalo con el número de observaciones, una medida de dispersión y el contexto temporal. Si comparas grupos, especifica unidad, periodo y regla de inclusión.
ventas %>%
mutate(total = unidades * precio) %>%
group_by(producto) %>%
summarise(
n = n(),
promedio = mean(total),
mediana = median(total),
minimo = min(total),
maximo = max(total),
desviacion = sd(total),
.groups = "drop"
)Porcentajes con denominador visible
ventas %>%
mutate(total = unidades * precio) %>%
group_by(ciudad) %>%
summarise(ingresos = sum(total), .groups = "drop") %>%
mutate(porcentaje = ingresos / sum(ingresos))Si tu público no conoce R, no entregues solo la consola. Incluye una tabla limpia, un gráfico, tres conclusiones verificables y una sección de limitaciones. La claridad consiste en mostrar qué sabes, qué no sabes y qué necesitas medir después.
9. Ejercicios graduados con solución
Intenta cada reto antes de abrir la respuesta. Puede haber varias soluciones correctas si son legibles, producen el resultado esperado y explican los supuestos.
Reto 1 · Resumir un vector
Crea cinco gastos, calcula total, promedio y cuántos superan 500.
gastos <- c(250, 820, 430, 1200, 90)
sum(gastos)
mean(gastos)
sum(gastos > 500)Reto 2 · Filtrar y crear columna
Con clientes, conserva gasto mayor a 400 y calcula gasto por compra.
clientes %>%
filter(gasto > 400) %>%
mutate(gasto_por_compra = gasto / compras)Reto 3 · Agrupar por producto
Calcula unidades e ingresos por producto.
ventas %>%
mutate(total = unidades * precio) %>%
group_by(producto) %>%
summarise(unidades = sum(unidades), ingresos = sum(total), .groups = "drop")Reto 4 · Control de calidad
Detecta precios negativos y fechas faltantes.
ventas %>% filter(precio < 0 | is.na(fecha))Reto 5 · Elegir el gráfico
Para evolución por fecha usa líneas; para comparar ciudades usa barras; para explorar relación entre unidades y precio usa puntos.
Reto 6 · Explicar un resultado
Escribe una conclusión que contenga periodo, grupo, magnitud, comparación y limitación. Evita convertir una correlación en una afirmación causal.
10. Proyecto final: informe reproducible de ventas
Construye un informe que responda: ¿qué productos y ciudades aportaron más ingresos?, ¿cómo cambió el resultado por fecha?, ¿qué datos requieren revisión? Integra fundamentos, limpieza, transformaciones, gráficos y comunicación.
Datos mínimos
- Fecha de operación.
- Ciudad o región.
- Producto o categoría.
- Unidades, precio e importe.
- Identificador de pedido, si existe.
Estructura de carpetas
proyecto-ventas/
├─ datos/
│ ├─ originales/
│ └─ procesados/
├─ scripts/
│ ├─ 01_importar.R
│ ├─ 02_limpiar.R
│ └─ 03_graficos.R
├─ resultados/
├─ informe.Rmd
└─ README.mdEntregables
- README con objetivo, fuente, fecha de descarga y limitaciones.
- Script que importe y limpie sin pasos manuales ocultos.
- Tabla de calidad con faltantes, duplicados y rangos.
- Gráfico temporal y comparación por grupo.
- Resumen con tres hallazgos y dos preguntas siguientes.
Lista de revisión
- ¿El código corre desde una sesión nueva?
- ¿Las fechas y unidades monetarias son consistentes?
- ¿Las conclusiones se desprenden de los datos?
- ¿Se distinguen hechos, supuestos y recomendaciones?
- ¿Otra persona puede entender cómo repetirlo?
11. Glosario de consulta rápida
Argumento
Valor entregado a una función para controlar su comportamiento.
Data frame
Tabla de columnas relacionadas y filas de observaciones.
NA
Dato ausente; no significa automáticamente cero.
Pipe
Operador que conecta una salida con la siguiente transformación.
Factor
Estructura para categorías y niveles.
Join
Combina tablas usando una o más claves.
Vectorización
Aplicación de una operación a varios valores sin bucle explícito.
Reproducibilidad
Capacidad de repetir el proceso con los mismos insumos.
Sesgo
Distorsión sistemática que aleja una estimación de lo que se quiere medir.
Dispersión
Qué tanto se separan los valores del centro de los datos.
12. Preguntas frecuentes
¿Necesito matemáticas avanzadas para empezar?
No para comenzar. Conviene entender porcentajes, promedios y lectura de tablas; las fórmulas avanzadas se estudian cuando el problema las necesita. R automatiza cálculos, pero no sustituye la revisión de supuestos.
¿R o Python: cuál debo aprender?
Depende del objetivo. R destaca en estadística, visualización e informes; Python cubre análisis, automatización y desarrollo general. Aprende uno con profundidad y después transfiere conceptos.
¿Por qué mi promedio devuelve NA?
Existe al menos un valor ausente. Comprueba sum(is.na(x)) y decide si excluirlo con na.rm = TRUE. Si los faltantes se concentran en un grupo, el resultado puede quedar sesgado.
¿Cómo evito que cambien las rutas?
Usa un proyecto de RStudio, una estructura estable y rutas relativas. Evita rutas absolutas de tu computadora y documenta qué archivos son necesarios.
¿Cuándo está mal planteado un gráfico?
Cuando la geometría no responde la pregunta, el eje oculta diferencias, hay demasiadas categorías o el color dificulta la lectura. Escribe primero la frase que el lector debe entender y elige después la geometría.
¿Cómo sigo practicando después de la guía?
Elige un conjunto de datos público, formula una pregunta concreta, escribe un script reproducible y entrega un informe con limitaciones. Después repite el proyecto con otro periodo para probar si tu código realmente se reutiliza.
Recursos para continuar
Consulta la documentación oficial de CRAN, la referencia de ggplot2 y el libro abierto R for Data Science. Úsalos para verificar funciones, argumentos y cambios de versión.
Tu siguiente paso es comenzar el proyecto final: define una pregunta, conserva la fuente original y escribe primero una comprobación de calidad. Guarda esta página en favoritos para volver a cualquier módulo.