Programación · Lenguajes de programación
Tutorial de programación en R para principiantes
Respuesta corta
R es un lenguaje y entorno libre para estadística, análisis de datos y gráficos. Su idea central es la vectorización: las operaciones se aplican a vectores completos y a columnas de data frames de una sola vez, por lo que el código de análisis es corto. Esta página cubre la instalación de R, la ejecución de scripts, los vectores y tipos, el control de flujo, las funciones, las listas y data frames, los modelos estadísticos, los gráficos y el manejo de errores.
Qué es R y para qué se usa
R es un lenguaje y entorno libre y de código abierto para computación estadística y gráficos. Desciende del lenguaje S, desarrollado en Bell Labs, y lo mantiene el R Core Team. R está vectorizado: la mayoría de las operaciones trabajan con vectores de datos completos a la vez, lo que hace que el código de análisis de datos sea corto.
R lo usan estadísticos, científicos de datos, bioinformáticos, economistas e investigadores para limpiar datos, crear modelos estadísticos, visualizar y generar informes reproducibles. Hay miles de paquetes adicionales disponibles en CRAN (Comprehensive R Archive Network) y Bioconductor.
Instalar R y ejecutar Hello, world
Descarga R desde CRAN para Windows, macOS o Linux. Mucha gente instala también RStudio o Positron, que son IDE con editor, consola, visor de gráficos y panel de ayuda. Puedes escribir código directamente en la consola de R o guardarlo en un archivo .R.
# hello.R
print("Hello, world!")
cat("Hello, world!\n")Rscript hello.R
# [1] "Hello, world!"
# Hello, world!print muestra un valor como lo hace la consola, con el prefijo de índice [1]. cat escribe texto plano, así que el salto de línea lo añades tú.
Variables, tipos básicos y vectores
Asigna con <- (el estilo convencional) o con =. En R no hay escalares: un solo número es un vector de longitud 1. c() combina valores en un vector, y la aritmética se aplica elemento a elemento.
x <- 42 # numeric (double)
n <- 7L # integer (L suffix)
name <- "Ada" # character
ok <- TRUE # logical
class(x); class(n); class(name) # "numeric" "integer" "character"
v <- c(2, 4, 6, 8)
v * 10 # [1] 20 40 60 80
v[2] # [1] 4 (indexing starts at 1)
v[v > 4] # [1] 6 8
length(v); sum(v); mean(v) # 4 20 5
1:5 # [1] 1 2 3 4 5
seq(0, 1, by = 0.25) # [1] 0.00 0.25 0.50 0.75 1.00| Tipo | Ejemplo | Notas |
|---|---|---|
| numeric (double) | 3.14, 42 | valor por defecto para los números |
| integer | 42L | números enteros con el sufijo L |
| character | "text" | cadenas de texto |
| logical | TRUE, FALSE | NA significa un valor ausente |
| factor | factor(c("lo", "hi")) | datos categóricos con niveles fijos |
Control de flujo
R tiene if/else, for, while y repeat. Con vectores, la función vectorizada ifelse() suele ser mejor que un bucle.
temp <- 25
if (temp > 30) {
print("hot")
} else if (temp > 15) {
print("mild") # [1] "mild"
} else {
print("cold")
}
for (i in 1:3) {
cat("step", i, "\n") # step 1 / step 2 / step 3
}
scores <- c(45, 80, 62)
ifelse(scores >= 50, "pass", "fail")
# [1] "fail" "pass" "pass"if necesita un único TRUE o FALSE. Pasar un vector más largo a if es un error desde R 4.2; usa en su lugar any(), all() o ifelse().
Funciones
Las funciones se crean con function y se asignan a un nombre. La última expresión evaluada se devuelve automáticamente; return() solo hace falta para salir antes de tiempo. Los argumentos pueden tener valores por defecto y pasarse por nombre.
bmi <- function(weight_kg, height_m = 1.75) {
weight_kg / height_m^2
}
bmi(70) # [1] 22.85714
bmi(height_m = 1.6, weight_kg = 60) # [1] 23.4375
square <- function(x) x^2
square(1:4) # [1] 1 4 9 16 (vectorized)
sapply(c(1, 4, 9), sqrt) # [1] 1 2 3
(\(x) x + 1)(10) # [1] 11 (short lambda syntax)La sintaxis corta de lambda \(x) está disponible desde R 4.1, igual que el pipe nativo |>, que pasa el lado izquierdo como primer argumento: c(1, 4, 9) |> sqrt() |> sum() devuelve 6.
Estructuras de datos principales: vectores, listas y data frames
Además de los vectores atómicos, R tiene listas (que pueden contener valores de distintos tipos), matrices y data frames. Un data frame es una tabla en la que cada columna es un vector de la misma longitud; es la estructura central del análisis de datos.
person <- list(name = "Ann", age = 31, langs = c("R", "SQL"))
person$name # [1] "Ann"
person[["langs"]][2] # [1] "SQL"
df <- data.frame(
name = c("Ann", "Bo", "Cy"),
age = c(31, 25, 40),
city = c("Oslo", "Rome", "Oslo")
)
nrow(df) # [1] 3
df$age # [1] 31 25 40
df[df$age > 30, "name"] # [1] "Ann" "Cy"
df$senior <- df$age >= 40 # add a column
aggregate(age ~ city, data = df, FUN = mean)
# city age
# 1 Oslo 35.5
# 2 Rome 25.0
str(df) # compact structure summarydf[rows, columns] selecciona por posición, nombre o condición lógica. Dejar un lado vacío, como en df[1, ], significa todas las filas o todas las columnas.
Estadística y gráficos
Las funciones estadísticas vienen incluidas: summary, sd, quantile, cor, t.test y lm (modelos lineales), entre muchas otras. Los gráficos base dibujan un gráfico con una sola llamada.
set.seed(1)
x <- 1:20
y <- 3 * x + rnorm(20, sd = 2)
model <- lm(y ~ x)
round(coef(model), 2) # intercept near 0, slope near 3
summary(model)$r.squared # close to 1
plot(x, y, main = "y vs x")
abline(model, col = "red")La sintaxis de fórmula y ~ x significa «modela y en función de x» y se usa en las funciones de modelado. Para gráficos avanzados y manipulación de datos, la mayoría instala los paquetes del tidyverse, como ggplot2 y dplyr, con install.packages("tidyverse").
Manejo de errores
Lanza un error con stop() y una advertencia con warning(). Captúralos con tryCatch(), que acepta funciones manejadoras para error, warning y un bloque finally opcional.
safe_log <- function(x) {
if (!is.numeric(x)) stop("x must be numeric")
if (any(x <= 0)) warning("non-positive values give NaN or -Inf")
log(x)
}
result <- tryCatch(
safe_log("ten"),
error = function(e) {
message("Caught: ", conditionMessage(e))
NA
},
finally = message("done")
)
# Caught: x must be numeric
# done
result # [1] NAUn programa completo y pequeño: resumen de ventas
Este script construye una pequeña tabla de ventas, calcula los ingresos por región con R base e imprime la mejor región.
sales <- data.frame(
region = c("North", "South", "North", "East", "South"),
units = c(10, 4, 6, 8, 12),
price = c(2.5, 3.0, 2.5, 4.0, 3.0)
)
sales$revenue <- sales$units * sales$price
by_region <- aggregate(revenue ~ region, data = sales, FUN = sum)
by_region <- by_region[order(-by_region$revenue), ]
print(by_region, row.names = FALSE)
# region revenue
# South 48
# North 40
# East 32
best <- by_region$region[1]
cat(sprintf("Best region: %s (%.2f)\n", best, max(by_region$revenue)))
# Best region: South (48.00)Siguientes pasos
- An Introduction to R, el manual oficial en CRAN.
- La ayuda integrada: escribe
?meanohelp("lm")en la consola. - R for Data Science, de Hadley Wickham y colaboradores, gratuito en línea, para el enfoque del tidyverse.
- Los CRAN Task Views, que listan paquetes por campo, como econometría o aprendizaje automático.
Preguntas frecuentes
¿Es mejor R o Python para el análisis de datos?
Ambos son potentes. R tiene una amplia biblioteca de métodos estadísticos y excelentes gráficos, y es común en el ámbito académico y la bioestadística; Python es de propósito más general y domina la ingeniería de aprendizaje automático. Muchos analistas aprenden los dos.
¿Cuál es la diferencia entre <- y = en R?
Ambos asignan en el nivel superior, y <- es el estilo convencional. Dentro de una llamada a función, = da nombre a un argumento, de modo que f(x = 1) pasa un argumento en lugar de crear una variable.
¿Por qué R empieza a contar en 1?
R sigue la convención matemática y estadística, igual que su predecesor S, así que el primer elemento de un vector es v[1]. El índice 0 devuelve un vector vacío en lugar de un error.
¿Qué es el tidyverse?
El tidyverse es una colección de paquetes de R, entre ellos dplyr, ggplot2 y tidyr, que comparten un diseño coherente para importar, limpiar, transformar y graficar datos.
¿Cómo instalo un paquete de R?
Ejecuta install.packages("name") una vez para descargarlo de CRAN y luego library(name) en cada sesión para cargarlo.