在不同变量上运行 lm 的函数
Function which runs lm over different variables
我想创建一个函数,它可以 运行 对给定数据集中不同变量的回归模型(例如使用 lm)。在此函数中,我将指定我正在使用的数据集、因变量 y 和自变量 x 作为参数。我希望这是一个函数而不是循环,因为我想在脚本的各个位置调用代码。我的天真函数看起来像这样:
lmfun <- function(data, y, x) {
lm(y ~ x, data = data)
}
这个函数显然是行不通的,因为 lm 函数不能将 y 和 x 识别为数据集的变量。
我做了一些研究,偶然发现了以下有用的小插图:programming with dplyr。该小插图针对与我面临的类似问题提供了以下解决方案:
df <- tibble(
g1 = c(1, 1, 2, 2, 2),
g2 = c(1, 2, 1, 2, 1),
a = sample(5),
b = sample(5)
)
my_sum <- function(df, group_var) {
group_var <- enquo(group_var)
df %>%
group_by(!! group_var) %>%
summarise(a = mean(a))
}
我知道 lm 不是 dplyr 包中的一个函数,但我想提出一个与此类似的解决方案。我尝试了以下方法:
lmfun <- function(data, y, x) {
y <- enquo(y)
x <- enquo(x)
lm(!! y ~ !! x, data = data)
}
lmfun(mtcars, mpg, disp)
运行 此代码给出以下错误消息:
Error in is_quosure(e2) : argument "e2" is missing, with no default
有人知道如何修改代码以使其正常工作吗?
谢谢,
约斯特。
您可以使用 quo_name
和 formula
:
解决此问题
lmfun <- function(data, y, x) {
y <- enquo(y)
x <- enquo(x)
model_formula <- formula(paste0(quo_name(y), "~", quo_name(x)))
lm(model_formula, data = data)
}
lmfun(mtcars, mpg, disp)
# Call:
# lm(formula = model_formula, data = data)
#
# Coefficients:
# (Intercept) disp
# 29.59985 -0.04122
这是另一种选择:
编辑:
这是一个重构的答案
lmfun<-function(data,yname,xname){
formula1<-as.formula(paste(yname,"~",xname))
lm.fit<-do.call("lm",list(data=quote(data),formula1))
lm.fit
}
lmfun(mtcars,"mpg","disp")
原答案:
lmfun<-function(data,y,x){
formula1<-as.formula(y~x)
lm.fit<-do.call("lm",list(data=quote(data),formula1))
lm.fit
}
lmfun(mtcars,mtcars$mpg,mtcars$disp)
产量:
Call:
lm(formula = y ~ x, data = data)
Coefficients:
(Intercept) x
29.59985 -0.04122
如果参数未加引号,则在将quosure更改为字符串(quo_name
)后转换为符号(sym
)并评估lm
中的表达式(类似于OP的lm
)
的语法
library(rlang)
lmfun <- function(data, y, x) {
y <- sym(quo_name(enquo(y)))
x <- sym(quo_name(enquo(x)))
expr1 <- expr(!! y ~ !! x)
model <- lm(expr1, data = data)
model$call$formula <- expr1 # change the call formula
model
}
lmfun(mtcars, mpg, disp)
#Call:
#lm(formula = mpg ~ disp, data = data)
#Coefficients:
#(Intercept) disp
# 29.59985 -0.04122
如果我们要传递字符串,一个选项将使用 ensym
转换为符号,然后 quote
在 lm
中转换为符号
lmfun <- function(data, y, x) {
y <- ensym(y)
x <- ensym(x)
expr1 <- expr(!! y ~ !! x)
model <- lm(expr1, data = data)
model$call$formula <- expr1 # change the call formula
model
}
lmfun(mtcars, 'mpg', 'disp')
#Call:
#lm(formula = mpg ~ disp, data = data)
#Coefficients:
#(Intercept) disp
# 29.59985 -0.04122
注意:两个选项均来自tidyverse
另一个解决方案:
lmf2 <- function(data,y,x){
fml <- substitute(y~x, list(y=substitute(y), x=substitute(x)))
lm(eval(fml), data)
}
lmf2(mtcars, mpg, disp)
# Call:
# lm(formula = eval(fml), data = data)
#
# Coefficients:
# (Intercept) disp
# 29.59985 -0.04122
或者,等价地:
lmf3 <- function(data,y,x){
lm(eval(call("~", substitute(y), substitute(x))), data)
}
我想创建一个函数,它可以 运行 对给定数据集中不同变量的回归模型(例如使用 lm)。在此函数中,我将指定我正在使用的数据集、因变量 y 和自变量 x 作为参数。我希望这是一个函数而不是循环,因为我想在脚本的各个位置调用代码。我的天真函数看起来像这样:
lmfun <- function(data, y, x) {
lm(y ~ x, data = data)
}
这个函数显然是行不通的,因为 lm 函数不能将 y 和 x 识别为数据集的变量。
我做了一些研究,偶然发现了以下有用的小插图:programming with dplyr。该小插图针对与我面临的类似问题提供了以下解决方案:
df <- tibble(
g1 = c(1, 1, 2, 2, 2),
g2 = c(1, 2, 1, 2, 1),
a = sample(5),
b = sample(5)
)
my_sum <- function(df, group_var) {
group_var <- enquo(group_var)
df %>%
group_by(!! group_var) %>%
summarise(a = mean(a))
}
我知道 lm 不是 dplyr 包中的一个函数,但我想提出一个与此类似的解决方案。我尝试了以下方法:
lmfun <- function(data, y, x) {
y <- enquo(y)
x <- enquo(x)
lm(!! y ~ !! x, data = data)
}
lmfun(mtcars, mpg, disp)
运行 此代码给出以下错误消息:
Error in is_quosure(e2) : argument "e2" is missing, with no default
有人知道如何修改代码以使其正常工作吗?
谢谢,
约斯特。
您可以使用 quo_name
和 formula
:
lmfun <- function(data, y, x) {
y <- enquo(y)
x <- enquo(x)
model_formula <- formula(paste0(quo_name(y), "~", quo_name(x)))
lm(model_formula, data = data)
}
lmfun(mtcars, mpg, disp)
# Call:
# lm(formula = model_formula, data = data)
#
# Coefficients:
# (Intercept) disp
# 29.59985 -0.04122
这是另一种选择: 编辑: 这是一个重构的答案
lmfun<-function(data,yname,xname){
formula1<-as.formula(paste(yname,"~",xname))
lm.fit<-do.call("lm",list(data=quote(data),formula1))
lm.fit
}
lmfun(mtcars,"mpg","disp")
原答案:
lmfun<-function(data,y,x){
formula1<-as.formula(y~x)
lm.fit<-do.call("lm",list(data=quote(data),formula1))
lm.fit
}
lmfun(mtcars,mtcars$mpg,mtcars$disp)
产量:
Call:
lm(formula = y ~ x, data = data)
Coefficients:
(Intercept) x
29.59985 -0.04122
如果参数未加引号,则在将quosure更改为字符串(quo_name
)后转换为符号(sym
)并评估lm
中的表达式(类似于OP的lm
)
library(rlang)
lmfun <- function(data, y, x) {
y <- sym(quo_name(enquo(y)))
x <- sym(quo_name(enquo(x)))
expr1 <- expr(!! y ~ !! x)
model <- lm(expr1, data = data)
model$call$formula <- expr1 # change the call formula
model
}
lmfun(mtcars, mpg, disp)
#Call:
#lm(formula = mpg ~ disp, data = data)
#Coefficients:
#(Intercept) disp
# 29.59985 -0.04122
如果我们要传递字符串,一个选项将使用 ensym
转换为符号,然后 quote
在 lm
lmfun <- function(data, y, x) {
y <- ensym(y)
x <- ensym(x)
expr1 <- expr(!! y ~ !! x)
model <- lm(expr1, data = data)
model$call$formula <- expr1 # change the call formula
model
}
lmfun(mtcars, 'mpg', 'disp')
#Call:
#lm(formula = mpg ~ disp, data = data)
#Coefficients:
#(Intercept) disp
# 29.59985 -0.04122
注意:两个选项均来自tidyverse
另一个解决方案:
lmf2 <- function(data,y,x){
fml <- substitute(y~x, list(y=substitute(y), x=substitute(x)))
lm(eval(fml), data)
}
lmf2(mtcars, mpg, disp)
# Call:
# lm(formula = eval(fml), data = data)
#
# Coefficients:
# (Intercept) disp
# 29.59985 -0.04122
或者,等价地:
lmf3 <- function(data,y,x){
lm(eval(call("~", substitute(y), substitute(x))), data)
}