Guía educativa original · JP Studio

R desde cero hasta un nivel intermedio: aprende analizando datos reales.

Una ruta extensa para comprender R y RStudio, crear objetos, trabajar con tablas, limpiar datos, construir gráficos, reutilizar funciones, documentar resultados y entregar un proyecto reproducible.

12 módulosEjemplos comentadosEjercicios con soluciónProyecto finalResponsive
ESPACIO PUBLICITARIO

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.

Regla central: un análisis útil debe poder repetirse. Conserva los datos originales, escribe el código en un script, documenta los supuestos y separa los resultados de las decisiones.

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

Comentarios, 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)
Analogía: un objeto es una caja etiquetada. R puede abrirla, transformarla y guardar el resultado en otra caja; si sobrescribes la primera, pierdes la versión anterior.

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 Ventas con ventas; 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.

TipoEjemploUso
Numérico12.5Precios, cantidades y mediciones.
Carácter"México"Nombres, categorías y códigos.
LógicoTRUEFiltros y condiciones.
Fechaas.Date("2026-08-14")Orden temporal y periodos.
AusenteNADato 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)
Inspección mínima: usa 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% validos

Valores 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)
Buenas funciones: una función debe tener una responsabilidad principal. Si filtra, calcula, exporta y grafica a la vez, será más difícil probarla y mantenerla.

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")
Control: un aumento inesperado de filas después de un 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.

Bitácora: conserva 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()
Accesibilidad: no uses solo color. Añade etiquetas, formas, líneas o facetas, y prueba si el mensaje sigue claro en escala de grises.

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.

Plantilla: “Durante [periodo], [grupo] registró [resultado]. Frente a [comparación], la diferencia fue [magnitud]. La lectura está limitada por [limitación].”

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

Entregables

  1. README con objetivo, fuente, fecha de descarga y limitaciones.
  2. Script que importe y limpie sin pasos manuales ocultos.
  3. Tabla de calidad con faltantes, duplicados y rangos.
  4. Gráfico temporal y comparación por grupo.
  5. 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?
Ampliación intermedia: añade parámetros para cambiar el periodo, genera un informe HTML con R Markdown y valida columnas obligatorias antes de comenzar.

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.

↑ Volver a la guía principal