Mostrando las entradas con la etiqueta funciones. Mostrar todas las entradas
Mostrando las entradas con la etiqueta funciones. Mostrar todas las entradas

jueves, 9 de julio de 2015

Manipulación de los nombres de las funciones 1

[Lenguajes: R]

Problema

En R las funciones se guardan en variables, por ejemplo, una función que simplemente imprima su argumento podría darse por
miFun <- function(x) {print(x)}
# La ejecutamos así
miFun("cualquier cosa")
## [1] "cualquier cosa"
Puede ocurrir, sin embargo, que el nombre de la función esté contenida, como un string de caracteres, en otra variable:
nombreF <- "miFun"
Supongamos que no se tiene acceso a la variable miFun, sino únicamente a la variable nombreF. ¿De qué manera se podría ejecutar la función a partir de eso? Esto es, tener algo como:
EJECUTA(nombreF)("algún argumento")
## [1] "algún argumento"

Solución

Para resolver este problema, recurriremos a dos funciones primitivas del lenguaje, assign() y get(), que permiten asignar variables, y extraer valores de variables a partir de sus nombres dados como strings de caracteres:
# La asignación 
x <- 3
# Es lo mismo que:
assign("x", 3)
# La extracción de un valor:
x
## [1] 3
# Es lo mismo que
get("x")
## [1] 3
Por otra parte, la sintaxis de este lenguaje permite ejecutar una función a partir de la variable que ha servido para definirla, o a partir del nombre de la variable dada como un string de caracteres constante. Así,
miFun("cualquier cosa")
## [1] "cualquier cosa"
tiene el mismo resultado que:
"miFun"("cualquier cosa") # NOTE las comillas en el nombre de la función
## [1] "cualquier cosa"
Combinando todo esto, llegamos al resultado deseado de ejecutar la función a partir de una variable que contiene su nombre (nombreF), de la siguiente manera:
get(nombreF)("cualquier cosa") 
## [1] "cualquier cosa"

Si quieres ver este mismo post en mis publicaciones de Rpubs:

martes, 7 de julio de 2015

Funciones acumulativas 1

[Lenguajes: R]

Problema

En R hay varias funciones acumulativas, que operan sobre un vector de datos. Por ejemplo, la función sum(), hace la sumatoria de los números contenidos en el vector que se le pasa como argumento:

sum(c(8,-2,5))
## [1] 11

Otro ejemplo es la función prod(), que, de manera similar a la anterior, hace el producto.

La pregunta que surge es: ¿Hay una función que permita hacer lo mismo, pero para un operador, o función, arbitraria?

Solución

La respuesta a la pregunta anterior es sí, y el nombre de dicha función es Reduce(), que toma al menos los siguientes argumentos:

  • el operador o función que se aplica
  • el vector de datos

Por ejemplo, para hacer una sumatoria como la del ejemplo anterior, con Reduce() se haría así:

Reduce('+', c(8,-2,5)) # Nótese que el operador va con ''
## [1] 11

Para cualquier otro operador, digamos la división:

Reduce('/', c(8,-2,5)) # Nótese que el operador va con ''
## [1] -0.8

Lo interesante de esta función es que admite, como primer argumento, cualquier función de dos argumentos, particularmente, las que nosotros mismos pudieramos escribir o crear.

Por ejemplo:

# Sea 'ff' una función que multiplica por 2 el primer argumento y
# ese resultado lo divide por el segundo argumento:
ff <- function (x, y) {
    2*x / y
}
# Apliquemos secuencialmente esta función a los elementos de
# un vector
Reduce(ff, c(8,-2,5)) # Reduce admite ff, y también 'ff'
## [1] -3.2

Una característica interesante de Reduce(), es que mediante su argumento, opcional, accumulate, se le puede indicar que entregue cada uno de los resultados intermedios de la operación. Para ejemplificar esto, supóngase que se cuenta en un vector con las alturas individuales de cada uno de los pisos de un edificio y que se quiere saber, desde el suelo, cuál es la altura total de cada uno de los niveles del edificio. El problema se resuelve fácilmente así:

# Vector de alturas de los pisos individuales:
alturas <- c(3.10, 3.15, 3.05, 2.95, 3.10, 3.20)
# Niveles, desde el suelo
niveles <- Reduce('+', alturas, accumulate = TRUE)
niveles
## [1]  3.10  6.25  9.30 12.25 15.35 18.55

Si quieres ver este mismo post en mis publicaciones de Rpubs: