从 lapply 调用的函数中控制提供给 lm() 的参数范围
control scoping of arguments supplied to lm() from whithin a function called by lapply
我有一个函数,它接受一个数据集,提取不同的变量,然后从这些变量中建立线性模型(它期望最后一列中的响应)。我希望这些模型调用的 data
参数使用全局环境中的对象,以便我可以使用此函数之外的其他函数来操作它们。以下给出了提供单个数据集时的预期行为。
make_mods <- function(dataset) {
make_mod <- function(x){
response <- names(dataset)[length(dataset)]
form <- paste0(response, " ~ ", x)
form <- as.formula(form)
bquote( lm(.(form), data = .(d_sub)) ) # Unevaluated to show output
}
d_sub <- substitute(dataset)
vars <- names(dataset)[-length(dataset)]
mods <- lapply(vars, make_mod)
return(mods)
}
# Make some different datasets
ex1 <- ex2 <- ex3 <- mtcars[c(3,4,6,1)]
new_data <- function(x) {
x + rnorm(length(x), mean = 0, sd = sd(x))
}
ex2[-length(ex2)] <- lapply(ex2[-length(ex2)], new_data)
ex3[-length(ex3)] <- lapply(ex3[-length(ex3)], new_data)
make_mods(ex1)
我也想在lapply
内使用这个功能
# List of datasets for testing function with lapply
ex_l <- mget(c("ex1", "ex2", "ex3"))
lapply(ex_l, make_mods)
但是这里的模型调用最终看起来像这样:lm(mpg ~ disp, data = X[[i]])
当然,这个模型调用不会在默认环境中求值(实际函数在函数中求值模型调用)。所需的输出是一个模型列表列表,如下所示:lm(mpg ~ disp, data = ex_l[["ex1"]])
,即它们具有有效的调用,其中包含引用全局环境中数据帧的 data
个参数。
我已经尝试过将名称传递给 lapply
以及从 lapply
调用 make_mods
的不同包装函数,但它看起来像我的函数,仅使用 substitute
从全局环境调用时给出预期的行为。我不熟悉范围界定和环境。 如何让我的函数在从全局环境传递数据帧和从 lapply
内部传递数据帧时提供所需的 lm
调用。
我唯一能想到的就是在我的 make mods 函数中添加一个 if 语句来测试输入是否为调用。如果是调用,它期望它是对全局环境中的数据集的调用。
make_mods <- function(dataset) {
make_mod <- function(x){
response <- names(dataset)[length(dataset)]
form <- paste0(response, " ~ ", x)
form <- as.formula(form)
bquote( lm(.(form), data = .(d_sub)) )
}
if(is.call(dataset)) {
d_sub <- dataset
dataset <- eval(dataset)
} else {
d_sub <- substitute(dataset)
}
vars <- names(dataset)[-length(dataset)]
mods <- lapply(vars, make_mod)
return(mods)
}
然后我可以这样使用lapply
:
out <- lapply(names(ex_l), function(x){
g <- bquote(ex_l[[.(x)]])
make_mods(g)
})
names(out) <- names(ex_l)
这给了我这个:
$ex1
$ex1[[1]]
lm(mpg ~ disp, data = ex_l[["ex1"]])
$ex1[[2]]
lm(mpg ~ hp, data = ex_l[["ex1"]])
$ex1[[3]]
lm(mpg ~ wt, data = ex_l[["ex1"]])
<<output truncated>>
也许不是一个优雅的解决方案,但它确实有效。
我有一个函数,它接受一个数据集,提取不同的变量,然后从这些变量中建立线性模型(它期望最后一列中的响应)。我希望这些模型调用的 data
参数使用全局环境中的对象,以便我可以使用此函数之外的其他函数来操作它们。以下给出了提供单个数据集时的预期行为。
make_mods <- function(dataset) {
make_mod <- function(x){
response <- names(dataset)[length(dataset)]
form <- paste0(response, " ~ ", x)
form <- as.formula(form)
bquote( lm(.(form), data = .(d_sub)) ) # Unevaluated to show output
}
d_sub <- substitute(dataset)
vars <- names(dataset)[-length(dataset)]
mods <- lapply(vars, make_mod)
return(mods)
}
# Make some different datasets
ex1 <- ex2 <- ex3 <- mtcars[c(3,4,6,1)]
new_data <- function(x) {
x + rnorm(length(x), mean = 0, sd = sd(x))
}
ex2[-length(ex2)] <- lapply(ex2[-length(ex2)], new_data)
ex3[-length(ex3)] <- lapply(ex3[-length(ex3)], new_data)
make_mods(ex1)
我也想在lapply
# List of datasets for testing function with lapply
ex_l <- mget(c("ex1", "ex2", "ex3"))
lapply(ex_l, make_mods)
但是这里的模型调用最终看起来像这样:lm(mpg ~ disp, data = X[[i]])
当然,这个模型调用不会在默认环境中求值(实际函数在函数中求值模型调用)。所需的输出是一个模型列表列表,如下所示:lm(mpg ~ disp, data = ex_l[["ex1"]])
,即它们具有有效的调用,其中包含引用全局环境中数据帧的 data
个参数。
我已经尝试过将名称传递给 lapply
以及从 lapply
调用 make_mods
的不同包装函数,但它看起来像我的函数,仅使用 substitute
从全局环境调用时给出预期的行为。我不熟悉范围界定和环境。 如何让我的函数在从全局环境传递数据帧和从 lapply
内部传递数据帧时提供所需的 lm
调用。
我唯一能想到的就是在我的 make mods 函数中添加一个 if 语句来测试输入是否为调用。如果是调用,它期望它是对全局环境中的数据集的调用。
make_mods <- function(dataset) {
make_mod <- function(x){
response <- names(dataset)[length(dataset)]
form <- paste0(response, " ~ ", x)
form <- as.formula(form)
bquote( lm(.(form), data = .(d_sub)) )
}
if(is.call(dataset)) {
d_sub <- dataset
dataset <- eval(dataset)
} else {
d_sub <- substitute(dataset)
}
vars <- names(dataset)[-length(dataset)]
mods <- lapply(vars, make_mod)
return(mods)
}
然后我可以这样使用lapply
:
out <- lapply(names(ex_l), function(x){
g <- bquote(ex_l[[.(x)]])
make_mods(g)
})
names(out) <- names(ex_l)
这给了我这个:
$ex1
$ex1[[1]]
lm(mpg ~ disp, data = ex_l[["ex1"]])
$ex1[[2]]
lm(mpg ~ hp, data = ex_l[["ex1"]])
$ex1[[3]]
lm(mpg ~ wt, data = ex_l[["ex1"]])
<<output truncated>>
也许不是一个优雅的解决方案,但它确实有效。