R
Tutorial R: Funciones
Aprende a crear funciones en R, manejar argumentos posicionales, nombrados y predeterminados, y dominar el retorno de valores para código modular.
Aprende R y certifícateDefinición y sintaxis de funciones en R
Las funciones son bloques de código reutilizables que realizan una tarea específica en R. Funcionan como pequeñas "máquinas" que pueden recibir datos, procesarlos y devolver un resultado. El uso de funciones nos permite organizar mejor nuestro código, evitar repeticiones y hacer nuestros programas más legibles y mantenibles.
Estructura básica de una función
En R, una función se define utilizando la palabra clave function
. La estructura general es:
nombre_funcion <- function(argumentos) {
# Cuerpo de la función
# Código que realiza operaciones
return(valor) # Opcional: valor que devuelve la función
}
Los componentes principales de una función son:
- Nombre: Identificador que usaremos para llamar a la función
- Argumentos: Valores que la función recibe para trabajar
- Cuerpo: Conjunto de instrucciones que la función ejecuta
- Valor de retorno: Resultado que la función devuelve al finalizar
Creando funciones simples
Veamos un ejemplo sencillo de una función que calcula el área de un rectángulo:
calcular_area <- function(largo, ancho) {
area <- largo * ancho
return(area)
}
Para utilizar esta función, simplemente la llamamos con los valores que queremos procesar:
# Calculamos el área de un rectángulo de 5x3
mi_area <- calcular_area(5, 3)
print(mi_area) # Muestra 15
Funciones sin argumentos
También podemos crear funciones que no requieran ningún argumento:
saludar <- function() {
mensaje <- "¡Hola, bienvenido a R!"
return(mensaje)
}
# Llamamos a la función
saludo <- saludar()
print(saludo)
El retorno implícito
En R, si no utilizamos la instrucción return()
, la función devolverá automáticamente el resultado de la última expresión evaluada. Esto se conoce como retorno implícito:
# Función con retorno implícito
calcular_area_implicita <- function(largo, ancho) {
largo * ancho # Esta expresión será el valor devuelto
}
# Ambas llamadas producen el mismo resultado
area1 <- calcular_area(5, 3)
area2 <- calcular_area_implicita(5, 3)
print(area1) # 15
print(area2) # 15
Aunque el retorno implícito funciona, es una buena práctica usar return()
explícitamente en funciones complejas para mejorar la legibilidad del código.
Funciones con múltiples instrucciones
Las funciones pueden contener tantas líneas de código como necesitemos:
analizar_numero <- function(x) {
# Realizamos varios cálculos
cuadrado <- x^2
cubo <- x^3
raiz <- sqrt(x)
# Creamos un vector con los resultados
resultados <- c(original = x, cuadrado = cuadrado,
cubo = cubo, raiz = raiz)
return(resultados)
}
# Analizamos el número 4
analisis <- analizar_numero(4)
print(analisis)
Documentación de funciones
Es una buena práctica documentar nuestras funciones para que otros (o nosotros mismos en el futuro) entiendan qué hacen:
#' Calcula el área de un círculo
#'
#' @param radio El radio del círculo
#' @return El área del círculo
area_circulo <- function(radio) {
if (radio < 0) {
stop("El radio no puede ser negativo")
}
area <- pi * radio^2
return(area)
}
Verificación de argumentos
Es importante validar los argumentos que recibe nuestra función para evitar errores:
calcular_promedio <- function(numeros) {
# Verificamos que el argumento sea un vector numérico
if (!is.numeric(numeros)) {
stop("El argumento debe ser un vector numérico")
}
# Verificamos que no esté vacío
if (length(numeros) == 0) {
warning("Vector vacío, devolviendo NA")
return(NA)
}
# Calculamos el promedio
suma <- sum(numeros)
cantidad <- length(numeros)
promedio <- suma / cantidad
return(promedio)
}
# Probamos la función
calcular_promedio(c(10, 20, 30, 40)) # Devuelve 25
Alcance de variables
Las variables definidas dentro de una función tienen un alcance local, lo que significa que solo existen dentro de la función:
mi_funcion <- function() {
variable_local <- 10
print(paste("Dentro de la función:", variable_local))
return(variable_local)
}
resultado <- mi_funcion()
# Esto generaría un error porque variable_local no existe fuera de la función
# print(variable_local)
Anidamiento de funciones
Podemos definir funciones dentro de otras funciones. Las funciones internas solo son accesibles desde la función que las contiene:
calcular_estadisticas <- function(datos) {
# Función interna para calcular la varianza
calcular_varianza <- function(valores) {
media <- mean(valores)
suma_cuadrados <- sum((valores - media)^2)
varianza <- suma_cuadrados / length(valores)
return(varianza)
}
# Usamos la función interna
media <- mean(datos)
varianza <- calcular_varianza(datos)
return(list(media = media, varianza = varianza))
}
# Probamos la función
numeros <- c(2, 4, 6, 8, 10)
estadisticas <- calcular_estadisticas(numeros)
print(estadisticas)
Las funciones son uno de los pilares fundamentales de la programación en R, ya que nos permiten escribir código modular, reutilizable y más fácil de mantener. Dominar la creación de funciones es esencial para avanzar en el aprendizaje de este lenguaje.
Argumentos posicionales, nombrados y predeterminados
Cuando trabajamos con funciones en R, la forma en que pasamos los argumentos puede hacer nuestro código más flexible y legible. R ofrece tres métodos principales para proporcionar argumentos a las funciones: posicionales, nombrados y predeterminados.
Argumentos posicionales
Los argumentos posicionales son aquellos que se pasan a una función en el mismo orden en que fueron definidos. Este es el método más básico y común para llamar a funciones:
# Definimos una función con tres argumentos
dibujar_rectangulo <- function(alto, ancho, color) {
mensaje <- paste("Dibujando un rectángulo de", alto, "x", ancho, "en color", color)
return(mensaje)
}
# Llamada con argumentos posicionales
resultado <- dibujar_rectangulo(5, 10, "rojo")
print(resultado) # "Dibujando un rectángulo de 5 x 10 en color rojo"
En este ejemplo, R asigna el valor 5
al parámetro alto
, 10
al parámetro ancho
y "rojo"
al parámetro color
, basándose exclusivamente en la posición de cada argumento en la llamada.
La principal ventaja de los argumentos posicionales es su brevedad. Sin embargo, pueden generar confusión cuando una función tiene muchos parámetros o cuando no recordamos el orden exacto de los mismos.
Argumentos nombrados
Los argumentos nombrados nos permiten especificar explícitamente a qué parámetro corresponde cada valor, independientemente del orden:
# Usando argumentos nombrados
resultado <- dibujar_rectangulo(ancho = 10, color = "azul", alto = 5)
print(resultado) # "Dibujando un rectángulo de 5 x 10 en color azul"
Observa cómo, a pesar de haber cambiado el orden de los argumentos, la función sigue funcionando correctamente porque cada valor está explícitamente asociado a su parámetro.
Los argumentos nombrados ofrecen varias ventajas:
- Claridad: Hacen el código más legible, especialmente con funciones que tienen muchos parámetros
- Flexibilidad: Permiten proporcionar los argumentos en cualquier orden
- Seguridad: Reducen la posibilidad de errores por confusión en el orden de los parámetros
Combinación de argumentos posicionales y nombrados
En R, podemos combinar ambos enfoques en una misma llamada a función:
# Combinando argumentos posicionales y nombrados
resultado <- dibujar_rectangulo(5, ancho = 10, color = "verde")
print(resultado) # "Dibujando un rectángulo de 5 x 10 en color verde"
Sin embargo, es importante seguir esta regla: los argumentos posicionales deben aparecer siempre antes que los nombrados. El siguiente código generaría un error:
# Esto generaría un error
# resultado <- dibujar_rectangulo(alto = 5, 10, "verde")
Argumentos predeterminados
Los argumentos predeterminados (o valores por defecto) nos permiten especificar valores que se utilizarán cuando el usuario no proporcione un valor para ese parámetro:
# Función con argumentos predeterminados
crear_usuario <- function(nombre, edad = 30, ciudad = "Madrid") {
perfil <- paste(nombre, "tiene", edad, "años y vive en", ciudad)
return(perfil)
}
Esta función tiene tres parámetros, pero solo nombre
es obligatorio. Los parámetros edad
y ciudad
tienen valores predeterminados que se utilizarán si no se proporcionan explícitamente.
Veamos diferentes formas de llamar a esta función:
# Solo proporcionamos el argumento obligatorio
usuario1 <- crear_usuario("Ana")
print(usuario1) # "Ana tiene 30 años y vive en Madrid"
# Proporcionamos nombre y edad, pero usamos el valor predeterminado para ciudad
usuario2 <- crear_usuario("Carlos", 25)
print(usuario2) # "Carlos tiene 25 años y vive en Madrid"
# Proporcionamos todos los argumentos
usuario3 <- crear_usuario("Elena", 42, "Barcelona")
print(usuario3) # "Elena tiene 42 años y vive en Barcelona"
# Usando argumentos nombrados podemos omitir argumentos intermedios
usuario4 <- crear_usuario(nombre = "Pablo", ciudad = "Valencia")
print(usuario4) # "Pablo tiene 30 años y vive en Valencia"
Buenas prácticas con argumentos
Para escribir código más mantenible y claro, considera estas recomendaciones:
- Coloca los argumentos obligatorios al principio de la definición de la función
- Usa argumentos nombrados cuando llames a funciones con muchos parámetros
- Proporciona valores predeterminados razonables que cubran los casos de uso más comunes
- Documenta claramente el propósito de cada argumento
Verificación de argumentos con valores predeterminados
Podemos combinar los valores predeterminados con la verificación de argumentos para crear funciones más robustas:
calcular_descuento <- function(precio, porcentaje = 10, maximo = 50) {
# Verificamos que los argumentos sean válidos
if (!is.numeric(precio) || precio <= 0) {
stop("El precio debe ser un número positivo")
}
if (!is.numeric(porcentaje) || porcentaje < 0 || porcentaje > 100) {
stop("El porcentaje debe estar entre 0 y 100")
}
# Calculamos el descuento
descuento <- precio * (porcentaje / 100)
# Aplicamos el límite máximo si corresponde
if (!is.null(maximo) && descuento > maximo) {
descuento <- maximo
}
return(list(precio_original = precio,
descuento = descuento,
precio_final = precio - descuento))
}
# Probamos la función con diferentes combinaciones de argumentos
calcular_descuento(100) # 10% de descuento por defecto
calcular_descuento(100, 20) # 20% de descuento
calcular_descuento(500, 15, 60) # 15% con máximo personalizado
calcular_descuento(precio = 200, maximo = 30) # Omitimos el argumento intermedio
Argumentos especiales: puntos suspensivos (...)
R también permite crear funciones que acepten un número variable de argumentos mediante el parámetro especial ...
(puntos suspensivos):
sumar_valores <- function(...) {
# Capturamos todos los argumentos en una lista
argumentos <- list(...)
# Verificamos que todos sean numéricos
for (i in seq_along(argumentos)) {
if (!is.numeric(argumentos[[i]])) {
stop("Todos los argumentos deben ser numéricos")
}
}
# Sumamos todos los valores
total <- sum(unlist(argumentos))
return(total)
}
# Podemos llamar a la función con cualquier número de argumentos
sumar_valores(1, 2, 3) # Devuelve 6
sumar_valores(10, 20, 30, 40, 50) # Devuelve 150
Este mecanismo es especialmente útil cuando queremos crear funciones envoltorio que pasen argumentos a otras funciones:
graficar_mejorado <- function(datos, ...) {
# Establecemos algunos parámetros por defecto
par(mar = c(5, 4, 2, 1))
# Llamamos a la función plot pasando todos los argumentos adicionales
plot(datos, ...)
# Añadimos una cuadrícula
grid()
}
# Podemos usar esta función pasando argumentos que serán enviados a plot()
x <- 1:10
y <- x^2
graficar_mejorado(x, y, type = "b", col = "blue", main = "Gráfico cuadrático")
Dominar estos diferentes tipos de argumentos te permitirá crear funciones más flexibles y fáciles de usar, mejorando significativamente la calidad de tu código en R.
Retorno de valores
El retorno de valores es una característica fundamental de las funciones en R que permite devolver resultados después de ejecutar operaciones. Cuando una función completa su ejecución, puede proporcionar datos que serán utilizados en otras partes del programa.
Retorno explícito con return()
La forma más clara de devolver un valor desde una función es utilizando la instrucción return()
:
calcular_cuadrado <- function(numero) {
resultado <- numero^2
return(resultado)
}
# Llamamos a la función y capturamos el valor retornado
valor <- calcular_cuadrado(4)
print(valor) # Muestra 16
La instrucción return()
hace dos cosas importantes:
- Devuelve el valor especificado
- Finaliza inmediatamente la ejecución de la función
Este segundo punto es especialmente útil para crear salidas anticipadas en una función:
dividir_seguro <- function(numerador, denominador) {
# Verificación de seguridad
if (denominador == 0) {
return("Error: División por cero")
}
# Este código solo se ejecuta si el denominador no es cero
resultado <- numerador / denominador
return(resultado)
}
print(dividir_seguro(10, 2)) # Muestra 5
print(dividir_seguro(10, 0)) # Muestra "Error: División por cero"
Tipos de valores de retorno
En R, una función puede devolver prácticamente cualquier tipo de dato:
# Función que retorna un valor numérico
calcular_area_triangulo <- function(base, altura) {
return((base * altura) / 2)
}
# Función que retorna un vector
generar_secuencia <- function(inicio, fin) {
return(inicio:fin)
}
# Función que retorna una lista
analizar_texto <- function(texto) {
caracteres <- nchar(texto)
palabras <- length(strsplit(texto, "\\s+")[[1]])
mayusculas <- sum(grepl("[A-Z]", strsplit(texto, "")[[1]]))
return(list(
caracteres = caracteres,
palabras = palabras,
mayusculas = mayusculas
))
}
# Probamos las funciones
print(calcular_area_triangulo(5, 3)) # Muestra 7.5
print(generar_secuencia(5, 10)) # Muestra 5 6 7 8 9 10
resultado <- analizar_texto("Hola Mundo R")
print(resultado) # Muestra una lista con los análisis
Retorno de múltiples valores
A diferencia de otros lenguajes, R permite devolver múltiples valores de forma sencilla utilizando estructuras de datos como vectores, listas o data frames:
# Usando un vector nombrado
estadisticas_basicas <- function(numeros) {
return(c(
minimo = min(numeros),
maximo = max(numeros),
promedio = mean(numeros)
))
}
# Usando una lista (más flexible para diferentes tipos de datos)
analizar_datos <- function(numeros) {
return(list(
resumen = summary(numeros),
varianza = var(numeros),
es_normal = shapiro.test(numeros)$p.value > 0.05
))
}
# Probamos las funciones
datos <- c(12, 15, 21, 18, 9, 14)
print(estadisticas_basicas(datos))
analisis <- analizar_datos(datos)
print(analisis$resumen)
print(paste("¿Distribución normal?", analisis$es_normal))
Retorno implícito
Como ya vimos brevemente, R tiene la característica de retorno implícito: si no se especifica una instrucción return()
, la función devolverá automáticamente el resultado de la última expresión evaluada:
# Estas dos funciones son equivalentes
suma_explicita <- function(a, b) {
return(a + b)
}
suma_implicita <- function(a, b) {
a + b # La última expresión evaluada se retorna automáticamente
}
print(suma_explicita(3, 4)) # Muestra 7
print(suma_implicita(3, 4)) # También muestra 7
Este comportamiento es útil para escribir funciones concisas, especialmente cuando son simples:
# Función concisa para calcular el área de un círculo
area_circulo <- function(radio) pi * radio^2
# Función para verificar si un número es par
es_par <- function(x) x %% 2 == 0
print(area_circulo(3)) # Muestra 28.27433
print(es_par(4)) # Muestra TRUE
print(es_par(7)) # Muestra FALSE
Retorno condicional
Las funciones pueden devolver diferentes valores dependiendo de ciertas condiciones:
clasificar_temperatura <- function(temp) {
if (temp < 0) {
return("Congelación")
} else if (temp < 10) {
return("Muy frío")
} else if (temp < 20) {
return("Fresco")
} else if (temp < 30) {
return("Templado")
} else {
return("Caluroso")
}
}
print(clasificar_temperatura(-5)) # Muestra "Congelación"
print(clasificar_temperatura(25)) # Muestra "Templado"
Retorno invisible
R ofrece una función especial llamada invisible()
que permite devolver un valor sin mostrarlo automáticamente cuando la función se ejecuta directamente en la consola:
configurar_opciones <- function(tamano_fuente, color_fondo) {
# Simulamos configuración de opciones
opciones <- list(
tamano = tamano_fuente,
color = color_fondo,
timestamp = Sys.time()
)
# Devolvemos invisiblemente
invisible(opciones)
}
# Al llamar directamente, no muestra nada
configurar_opciones(12, "azul")
# Pero el valor está disponible si lo asignamos
config <- configurar_opciones(14, "gris")
print(config) # Ahora sí muestra el valor
Esta característica es útil para funciones que realizan acciones (como configurar algo o graficar) pero que también quieren proporcionar datos para uso opcional.
Captura y uso de valores retornados
Los valores devueltos por las funciones pueden ser:
- Asignados a variables
- Utilizados directamente en expresiones
- Pasados como argumentos a otras funciones
# Asignación a variable
resultado <- sqrt(16)
# Uso directo en expresión
if (es_par(7)) {
print("Es par")
} else {
print("Es impar")
}
# Pasando el resultado a otra función
datos <- c(1, 4, 9, 16, 25)
print(sum(sqrt(datos))) # Calcula la suma de las raíces cuadradas
Encadenamiento de funciones
Una práctica común en R es encadenar funciones, donde el valor retornado por una función se convierte en la entrada de otra:
# Procesamiento de datos encadenado
datos_procesados <- datos %>%
filtrar_valores_atipicos() %>%
normalizar() %>%
agrupar_por_categoria()
Este patrón es especialmente común cuando se utilizan paquetes como dplyr o magrittr que implementan el operador pipe (%>%
).
Buenas prácticas para el retorno de valores
Para escribir funciones más claras y mantenibles:
- Documenta claramente qué devuelve tu función
- Mantén consistencia en los tipos de retorno (evita que una función devuelva a veces un número y otras veces una cadena)
- Usa
return()
explícito en funciones complejas para mejorar la legibilidad - Considera devolver estructuras de datos nombradas para resultados múltiples
- Maneja adecuadamente los casos especiales y errores
#' Calcula el índice de masa corporal (IMC)
#'
#' @param peso Peso en kilogramos
#' @param altura Altura en metros
#' @return Un valor numérico que representa el IMC
calcular_imc <- function(peso, altura) {
# Validación de entradas
if (!is.numeric(peso) || !is.numeric(altura)) {
stop("Peso y altura deben ser valores numéricos")
}
if (peso <= 0 || altura <= 0) {
stop("Peso y altura deben ser valores positivos")
}
# Cálculo del IMC
imc <- peso / (altura^2)
return(imc)
}
El manejo efectivo de los valores de retorno es esencial para crear funciones útiles y reutilizables en R, permitiéndote construir programas más modulares y mantenibles.
Otros ejercicios de programación de R
Evalúa tus conocimientos de esta lección Funciones con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Todas las lecciones de R
Accede a todas las lecciones de R y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Instalación De R Y Rstudio
Introducción Y Entorno
Introducción A R
Introducción Y Entorno
Operadores
Sintaxis
Estructuras De Datos
Sintaxis
Funciones
Sintaxis
Estructuras De Control Iterativo
Sintaxis
Scopes Y Closures
Sintaxis
Estructuras De Control Condicional
Sintaxis
Funciones Anónimas
Sintaxis
Tipos De Datos Y Variables
Sintaxis
Sistema R6: Clases Referenciales Y Encapsulamiento
Programación Orientada A Objetos
Sistema S4: Clases Formales Y Validación
Programación Orientada A Objetos
Herencia Y Polimorfismo En R
Programación Orientada A Objetos
Sistemas De Oop En R
Programación Orientada A Objetos
Sistema S3: Clases Implícitas Y Métodos Genéricos
Programación Orientada A Objetos
Tidyverse Para Transformación De Datos
Manipulación De Datos
Lubridate Para Fechas Y Tiempo
Manipulación De Datos
Group_by Y Summarize Para Agrupación Y Resumen
Manipulación De Datos
Stringr Para Expresiones Regulares
Manipulación De Datos
Tidyr Para Limpieza De Valores Faltantes
Manipulación De Datos
Joins En R Para Combinación Y Relaciones De Tablas
Manipulación De Datos
Pivot_longer Y Pivot_wider Para Reestructuración
Manipulación De Datos
Mutate Y Transmute Para Transformación
Manipulación De Datos
Dplyr Para Filtrado Y Selección
Manipulación De Datos
Readr Y Read.csv Para Importar Datos
Manipulación De Datos
Gráficos Bivariantes En R
Visualización De Datos
Gráficos Univariantes En R
Visualización De Datos
Facetas En Ggplot2
Visualización De Datos
Personalización Y Temas
Visualización De Datos
Ggplot2 Para Visualización De Datos
Visualización De Datos
Gráficos Multivariantes En R
Visualización De Datos
Correlación En R
Estadística
Regresión Lineal En R
Estadística
Pruebas De Hipótesis En R
Estadística
Anova En R
Estadística
Estadística Descriptiva En R
Estadística
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender la estructura básica y sintaxis para definir funciones en R.
- Aprender a utilizar argumentos posicionales, nombrados y con valores predeterminados.
- Entender el concepto de retorno de valores, tanto explícito como implícito, y cómo manejar múltiples valores.
- Conocer buenas prácticas para la documentación, validación de argumentos y manejo del alcance de variables.
- Saber cómo usar argumentos especiales como los puntos suspensivos (...) para funciones flexibles.