seleccionar - tablas en r
¿Cómo se codifica una función R para que ''sepa'' buscar en ''datos'' las variables en otros argumentos? (3)
Así es como codificaría myfun() :
myfun <- function(a, b, data) {
eval(substitute(a + b), envir=data, enclos=parent.frame())
}
myfun(mpg, hp, mtcars)
# [1] 131.0 131.0 115.8 131.4 193.7 123.1 259.3 86.4 117.8 142.2 140.8 196.4
# [13] 197.3 195.2 215.4 225.4 244.7 98.4 82.4 98.9 118.5 165.5 165.2 258.3
# [25] 194.2 93.3 117.0 143.4 279.8 194.7 350.0 130.4
Si está familiarizado con with() , es interesante ver que funciona casi exactamente de la misma manera:
> with.default
# function (data, expr, ...)
# eval(substitute(expr), data, enclos = parent.frame())
# <bytecode: 0x016c3914>
# <environment: namespace:base>
En ambos casos, la idea clave es crear primero una expresión a partir de los símbolos pasados como argumentos y luego evaluar esa expresión utilizando data como el "entorno" de la evaluación.
La primera parte (por ejemplo, convertir a + b en la expresión mpg + hp ) es posible gracias a substitute() . La segunda parte es posible porque eval() fue bellamente diseñado, de modo que puede tomar un data.frame como su entorno de evaluación.
Si tu corres:
mod <- lm(mpg ~ factor(cyl), data=mtcars)
Se ejecuta, porque lm sabe buscar en mtcars para encontrar mpg y cyl.
Sin embargo, la mean(mpg) falla porque no puede encontrar mpg, así que sí mean(mtcars$mpg) .
¿Cómo se codifica una función para que sepa buscar las variables en ''datos''?
myfun <- function (a,b,data){
return(a+b)
}
Esto funcionará con:
myfun(mtcars$mpg, mtcars$hp)
pero fallará con:
myfun(mpg,hp, data=mtcars )
Aclamaciones
Esto no es exactamente como lo que pediste, pero si no conoces with() esta podría ser una opción:
myfun <- function (a,b){
return(a+b)
}
with(mtcars, myfun(mpg, hp))
Puede eliminar el argumento de data a myfun para esto.
lm "sabe" que buscar en su argumento de data porque en realidad construye una llamada a model.frame usando su propia llamada como base. Si observa el código de lm , verá la maquinaria necesaria en la primera docena de líneas aproximadamente.
Podría replicar esto para sus propios fines, pero si sus necesidades son más simples, no tiene que ir a la misma medida. Por ejemplo:
myfun <- function(..., data)
eval(match.call(expand.dots=FALSE)$...[[1]], data)
O simplemente mira evalq .