# 2.1 FUNCIONES
# 2.2 PROGRAMACIÓN < 005 >
# 2.3 FUNCIONES QUE EJECUTAN FUNCIONES Y PROGRAMAS < 023 >
# < 000 >
# 2.1 FUNCIONES
# nombre <- function(var_1 , var_2 , ... ) expresión/instrucción
# "%@%" <- function ( ... )
# Ejemplo: función de R^3 -> R
suma.rara <- function(x,y,z) x + y + z + min(x,y,z)
suma.rara(1,2,3)
# < 001 >
# Ejemplo: función de R^2 -> R^2
transforma <- function(x,y) c(x+y,x-y)
transforma(2,3)
# o bien:
resultado <- transforma(2,3)
resultado
length(resultado)
# < 002 >
# Los argumentos de la función pueden diversos tipos de objetos
# en R: vectores, matrices, texto, listas, etc:
oracion.dospalabras <- function(palabra1,palabra2) paste(palabra1,palabra2)
oracion.dospalabras("Quiero","vivir")
# < 003 >
matriz.alcuadrado <- function(matriz.cuadrada) matriz.cuadrada%*%matriz.cuadrada
matriz <- matrix(1:9,nrow=3,ncol=3,byrow=T)
matriz
matriz.alcuadrado(matriz)
# < 004 >
# En el caso particular de funciones de dos argumentos es posible definirlas
# como operadores binarios, por ejemplo:
"%#%" <- function(x,y) x+y+1
2%#%3
"%@%" <- function(matriz1,matriz2) (matriz1+matriz2)/2
matriz1 <- matrix(1:6,nrow=3,ncol=2)
matriz2 <- matrix(11:16,nrow=3,ncol=2)
matriz1; matriz2
matriz1%@%matriz2
# < 005 >
# 2.2 PROGRAMACIÓN
# Sintaxis general:
# nombre <- function( ...parámetros de entrada...) {
# instrucciones
# instrucciones
# ...
# }
# Editar la función:
# fix(nombre)
# Comentar con el símbolo #
# Salidas de información durante la ejecución: print
# Objeto(s) de salida del programa: return
# que puede(n) asignarse a una variable o presentarse
# directamente en la línea de comandos.
# < 006 >
# Instrucciones condicionales:
# If (prop_lógica) instrucción_1 [else instrucción_2]
# If (prop_lógica){
# instrucciones
# instrucciones
# }
# else{
# instrucciones
# instrucciones
# }
# ifelse ( prop_lógica, si , no )
# < 007 >
# Ciclos:
# for (variable in seq(...) ){
# instrucciones
# instrucciones
# ...
# }
# while (prop_lógica){
# instrucciones
# instrucciones
# ...
# }
#
# repeat{
# instrucciones
# instrucciones
# ...
# }
# break (terminar ciclo actual)
# next (pasa a la siguiente iteración)
# stop (terminar ejecución)
# < 008 >
# Nota: para escribir el código del programa, es posible usar
# el editor que para tal fin tiene R, o bien algún editor
# de texto externo, como el Bloc de Notas por ejemplo. Copie
# el siguiente código en la línea de comandos de R:
prueba <- function () # Esta es una funcion sin parámetros de entrada
{
print(noquote("Comienza ejecución..."))
matriz <- matrix(0,ncol=3,nrow=2)
uni <- "UNAM"
valor <- 3
lista <- list(elem1=matriz,elem2=uni,elem3=valor)
print(noquote("Hemos terminado!"))
return(lista)
}
# < 009 >
prueba # Despliega el código del programa
# < 010 >
prueba() # Ejecuta el programa
# < 011 >
# O bien podemos guardar en un objeto el resultado del programa:
resultado <- prueba()
resultado
resultado$elem1
# < 012 >
# En vez de escribir el código en el Bloc de Notas y luego copiarlo
# en la línea de comandos de R, se puede hacer lo siguiente:
# Utilice la función fix con el nombre del programa entre paréntesis,
# esto abrirá el editor de R para escribir código de programación.
# Ya capturado el código, cierre la venta del editor de código guardando
# los cambios (no ciere la ventana de R!)
# Si no hubo errores de compilación, con ejecutar el nombre de la función
# en la línea de comandos podrá verificar el código. Si hubo algún error,
# utilice, por ejemplo: prueba2 <- edit(), para volver al editor.
# Si utiliza la función fix para un programa o función ya existente, el editor
# de R le permitirá modificarlo.
# < 013 >
# Ejemplo:
fix(prueba2)
# Ya en el editor agregue una sola linea entre { y } como sigue: return(2+3)
# y luego cierre la venta del editor, guardando los cambios.
# El programa prueba2 ha sido creado.
# Para desplegar el código en la línea de comandos:
# < 014 >
prueba2
# < 015 >
# y para ejecutarlo:
prueba2()
# < 016 >
# Haremos ahora una modificación al programa, que generará un error:
fix(prueba2)
# y ya en el editor, sustituya + por $ y cierre el editor guardando cambios,
# y obtendrá el siguiente mensaje de error:
# Error en edit(name, file, title, editor) :
# inesperado constante numérica occurred on line 3
# use a command like
# x <- edit()
# to recover
# < 017 >
# Si usted ejecuta en la línea de comandos:
prueba2
# < 018 >
# Notará que despliega la versión de código anterior a la modificación que
# generó el error. Si usted quiere recuperar tal cual la última versión
# con todo y error entonces:
# < 019 >
prueba2 <- edit()
# < 020 >
# y corrija sustituyendo $ por + y guarde los cambios. Ejecute el programa:
prueba2()
# < 021 >
# Ejemplo: programa que construye la matriz de transición del proceso
# estocástico de dos jugadores que apuestan:
P.xy <- function(c1,c2,p){
#
# c1 y c2 enteros positivos
#
# capital jugador 1 = $c1 capital jugador 2 = $c2
#
# p = probabilidad de ganar del jugador 1
#
# apuesta por jugada = $1
#
# output = matriz de transicion de un paso
#
d <- c1 + c2 + 1 # numero de estados
P <- matrix(0, ncol=d, nrow=d)
P[1,1] <- 1 # estado absorbente 0
P[d,d] <- 1 # estado absorbente c1 + c2
for (i in 1:(d-2)){
P[i+1,i] <- 1-p # probabilidad de perder $1
P[i+1,i+2] <- p # probabilidad de ganar $1
}
return(P)
}
P.xy(4,7,0.7)
# < 022 >
# Las funciones y programas pueden llamar a otras funciones y programas
# previamente definidos, como se ilustrará en el siguiente ejemplo:
an <- function(n,i,vencida){
#
# calcula el valor presente o futuro de una anualidad
# de |n| pagos de $1 con tasa de interes i efectiva por periodo.
# Si n<0 entonces es valor presente, si n>0 es valor futuro.
# Si vencida=1 es anualidad vencida. Si vencida=0 es anticipada.
#
valor <- (((((1+i)^n)-1)*sign(n))/i)*exp((vencida==0)*log(1+i))
return(valor)
}
amort <- function(deuda,n,i){
#
# elabora tabla de amortizacion de una deuda de $<deuda>
# con n pagos vencidos iguales a una tasa de interes i
# efectiva por periodo de pago
#
# Observaciones: utiliza la funcion < an >
#
tabla <- matrix(0,ncol=5,nrow=(n+1))
colnames(tabla) <- c("periodo","pago","interes","amortizacion","saldo insoluto")
pago <- deuda/an((-1)*n,i,1)
tabla[1,5] <- deuda # deuda inicial
tabla[,1] <- 0:n # periodos de pago
for(t in 1:n){
tabla[t+1,2] <- pago # pago por periodo
tabla[t+1,3] <- i*tabla[t,5] # interes
tabla[t+1,4] <- tabla[t+1,2] - tabla[t+1,3] # pago a capital
tabla[t+1,5] <- tabla[t,5] - tabla[t+1,4] # saldo insoluto
}
return(round(tabla,2))
}
amort(1000,12,0.01)
# Por cierto, si fuera el caso de querer interrumpir
# la ejecución de un programa, puede hacerlo con la tecla Esc.
# < 023 >
# 2.3 FUNCIONES QUE EJECUTAN FUNCIONES Y PROGRAMAS
# apply sapply lapply mapply outer
# Definamos la matriz:
(X <- matrix(1:24,nrow=4))
# Notemos dos cosas: no se especificó el número de columnas, pero la
# cantidad de elementos en 1:24 permitió a R deducirlo. Segundo, al
# escribir toda la asignación a la variable X entre paréntesis produce
# el mismo efecto que lo siguiente
X <- matrix(1:24,nrow=4)
X
# < 024 >
# La función apply sirve para aplicar funciones a las columnas o filas
# de una matriz.
# Por ejemplo, para sumar por filas:
apply(X,1,sum)
# que es más sencillo que ejecutar
c(sum(X[1,]),sum(X[2,]),sum(X[3,]),sum(X[4,]))
# < 025 >
# y para sumar por columnas:
apply(X,2,sum)
# < 026 >
# Otro ejemplo de apply con una función definida por el usuario:
f <- function(x) min(x) + 1
apply(X,1,f)
# < 027 >
# Si se desea aplicar reiteradamente una función a un vector, se recomienda
# utilizar la función sapply:
sapply(3:7,seq) # Nótese que genera un objeto tipo lista
# < 028 >
# También puede ser utilizada con funciones o programas definidos
# por el usuario:
f <- function(x) x^2 + x
w <- c(1,3,10)
sapply(w,f)
# < 029 >
# Y para aplicar funciones o programas a los componentes de una lista
# utilizamos lapply, siempre y cuando la función se aplicable a todos
# los elementos de la lista
a <- c("Pumas","campeón")
b <- c(1,2,3,4,4,3,2,1)
c <- c(T,T,F)
lista <- list(a,b,c)
lapply(lista,length)
# < 030 >
# Lo siguiente generará un error:
lapply(lista,sum)
# < 040 >
x <- 1:4
y <- 100*(1:4)
x
y
f <- function(x,y) x + y + 1
f(x,y)
mapply(f,x,y)
# < 041 >
x <- 1:3
f(x,y) # Generará un mensaje de error
x
y
outer(x,y,f)