为什么我在将 "lm" 模型传递给 effectsize::effectsize() 时收到有关 stats::model.frame() 的错误?
Why am I getting an error about stats::model.frame() when passing an "lm" model to effectsize::effectsize()?
我在构建包装 lm()
的函数时遇到了一个奇怪的情况。具体来说,在将函数的模型输出传递给 effectsize::effectsize()
.
时,我收到一个与 stats::model.frame()
有关的错误
在下面的示例中有两种情况,A
和 B
。在 A
中,我定义了一个函数,它首先构建一个 formula
对象 my_formula <- as.formula(paste0(y, "~", x))
,然后将其传递给 lm()
。此函数 returns class "lm"
的一个对象。当我将该对象传递给 effectsize::effectsize()
时,出现错误:
Error in stats::model.frame(formula = my_formula, data = data_std, drop.unused.levels = TRUE) :
object 'my_formula' not found
奇怪的是,当我将同一个对象传递给 stats::model.frame()
时,它起作用了。
在场景 B
中,我构建了一个函数,其中公式在 lm()
内指定,而不是抢占式对象。在那种情况下,将输出传递给 effectsize()
是可行的。
可重现的例子
library(dplyr, warn.conflicts = FALSE)
library(effectsize)
## scenario A -- failing
my_lm_external_formula <- function(.dat, predicted, predictor){
my_formula <- as.formula(paste0(predicted, "~", predictor))
lm(formula = my_formula, data = .dat)
}
## the following line fails
my_lm_external_formula(.dat = mtcars, predicted = "mpg", predictor = "am") %>% effectsize()
#> Error in stats::model.frame(formula = my_formula, data = data_std, drop.unused.levels = TRUE): object 'my_formula' not found
## although this one works
my_lm_external_formula(.dat = mtcars, predicted = "mpg", predictor = "am") %>% stats::model.frame()
#> mpg am
#> Mazda RX4 21.0 1
#> Mazda RX4 Wag 21.0 1
#> Datsun 710 22.8 1
#> Hornet 4 Drive 21.4 0
#> Hornet Sportabout 18.7 0
#> Valiant 18.1 0
#> Duster 360 14.3 0
#> Merc 240D 24.4 0
#> Merc 230 22.8 0
#> Merc 280 19.2 0
#> Merc 280C 17.8 0
#> Merc 450SE 16.4 0
#> Merc 450SL 17.3 0
#> Merc 450SLC 15.2 0
#> Cadillac Fleetwood 10.4 0
#> Lincoln Continental 10.4 0
#> Chrysler Imperial 14.7 0
#> Fiat 128 32.4 1
#> Honda Civic 30.4 1
#> Toyota Corolla 33.9 1
#> Toyota Corona 21.5 0
#> Dodge Challenger 15.5 0
#> AMC Javelin 15.2 0
#> Camaro Z28 13.3 0
#> Pontiac Firebird 19.2 0
#> Fiat X1-9 27.3 1
#> Porsche 914-2 26.0 1
#> Lotus Europa 30.4 1
#> Ford Pantera L 15.8 1
#> Ferrari Dino 19.7 1
#> Maserati Bora 15.0 1
#> Volvo 142E 21.4 1
####
####
####
# scenario B -- working
my_lm_built_in_formula_via_pipe <- function(.dat, predicted, predictor){
.dat %>%
select(my_predicted = {{ predicted }}, my_predictor = {{ predictor }}) %>%
lm(my_predicted ~ my_predictor, data = .)
}
## both calls work:
my_lm_built_in_formula_via_pipe(.dat = mtcars, predicted = "mpg", predictor = "am") %>% effectsize()
#> # Standardization method: refit
#>
#> Parameter | Coefficient (std.) | 95% CI
#> -------------------------------------------------
#> (Intercept) | 2.94e-17 | [-0.29, 0.29]
#> my_predictor | 0.60 | [ 0.30, 0.90]
my_lm_built_in_formula_via_pipe(.dat = mtcars, predicted = "mpg", predictor = "am") %>% stats::model.frame()
#> my_predicted my_predictor
#> Mazda RX4 21.0 1
#> Mazda RX4 Wag 21.0 1
#> Datsun 710 22.8 1
#> Hornet 4 Drive 21.4 0
#> Hornet Sportabout 18.7 0
#> Valiant 18.1 0
#> Duster 360 14.3 0
#> Merc 240D 24.4 0
#> Merc 230 22.8 0
#> Merc 280 19.2 0
#> Merc 280C 17.8 0
#> Merc 450SE 16.4 0
#> Merc 450SL 17.3 0
#> Merc 450SLC 15.2 0
#> Cadillac Fleetwood 10.4 0
#> Lincoln Continental 10.4 0
#> Chrysler Imperial 14.7 0
#> Fiat 128 32.4 1
#> Honda Civic 30.4 1
#> Toyota Corolla 33.9 1
#> Toyota Corona 21.5 0
#> Dodge Challenger 15.5 0
#> AMC Javelin 15.2 0
#> Camaro Z28 13.3 0
#> Pontiac Firebird 19.2 0
#> Fiat X1-9 27.3 1
#> Porsche 914-2 26.0 1
#> Lotus Europa 30.4 1
#> Ford Pantera L 15.8 1
#> Ferrari Dino 19.7 1
#> Maserati Bora 15.0 1
#> Volvo 142E 21.4 1
由 reprex package (v2.0.0)
于 2021-08-15 创建
知道为什么我在场景 A 中出现错误(但在场景 B 中没有),以及为什么 effectsize()
失败而 stats::model.frame()
没有?
当您将 lm 对象传递给 effectsize() 时,它会在您当前的 R 环境中重新评估调用,而不是在创建公式变量的环境中,因此它会抛出错误,因为它找不到 my_formula
对于stats::model.frame
,因为你已经传递了lm对象,它只是拉出模型矩阵,不需要评估,你可以尝试传递它的公式:
x_formula <- function(.dat, predicted, predictor){
my_formula <- as.formula(paste0(predicted, "~", predictor))
my_formula
}
x_formula(.dat = mtcars,"am","gear") %>% stats::model.frame(data=mtcars)
Error in x_formula(.dat = mtcars, "am", "gear") :
could not find function "x_formula"
你可以看到它也失败了。所以这是一个错误的比较。
您可以强制计算调用,参见 this book chapter,但我不太确定这样做是否正确:
my_lm_external_formula <- function(.dat, predicted, predictor){
f = reformulate(response=predictor,termlabels=predicted)
fit = lm(f, data = .dat)
fit$call$formula = eval(f)
fit
}
my_lm_external_formula(.dat = mtcars, predicted = "mpg", predictor = "am") %>%
effectsize()
# Standardization method: refit
Parameter | Coefficient (std.) | 95% CI
------------------------------------------------
(Intercept) | -1.77e-17 | [-0.29, 0.29]
mpg | 0.60 | [ 0.30, 0.90]
您经常 运行 涉及 lm
的范围问题和 lm 对象的方法。我在使用该语言进行计算方面有很好的经验,但我不能保证您永远不会 运行 遇到问题。那里有一些方法不适用于尚未在与其调用相同的环境中创建的 lm 对象,一些不好的方法甚至需要在全局环境中创建它。
my_lm_external_formula <- function(.dat, predicted, predictor){
predicted <- as.name(predicted)
predictor <- as.name(predictor)
eval(bquote(lm(formula = .(predicted) ~ .(predictor), data = .dat)))
}
effectsize(
my_lm_external_formula(.dat = mtcars,
predicted = "mpg",
predictor = "am")
)
#works
我在构建包装 lm()
的函数时遇到了一个奇怪的情况。具体来说,在将函数的模型输出传递给 effectsize::effectsize()
.
stats::model.frame()
有关的错误
在下面的示例中有两种情况,A
和 B
。在 A
中,我定义了一个函数,它首先构建一个 formula
对象 my_formula <- as.formula(paste0(y, "~", x))
,然后将其传递给 lm()
。此函数 returns class "lm"
的一个对象。当我将该对象传递给 effectsize::effectsize()
时,出现错误:
Error in stats::model.frame(formula = my_formula, data = data_std, drop.unused.levels = TRUE) : object 'my_formula' not found
奇怪的是,当我将同一个对象传递给 stats::model.frame()
时,它起作用了。
在场景 B
中,我构建了一个函数,其中公式在 lm()
内指定,而不是抢占式对象。在那种情况下,将输出传递给 effectsize()
是可行的。
可重现的例子
library(dplyr, warn.conflicts = FALSE)
library(effectsize)
## scenario A -- failing
my_lm_external_formula <- function(.dat, predicted, predictor){
my_formula <- as.formula(paste0(predicted, "~", predictor))
lm(formula = my_formula, data = .dat)
}
## the following line fails
my_lm_external_formula(.dat = mtcars, predicted = "mpg", predictor = "am") %>% effectsize()
#> Error in stats::model.frame(formula = my_formula, data = data_std, drop.unused.levels = TRUE): object 'my_formula' not found
## although this one works
my_lm_external_formula(.dat = mtcars, predicted = "mpg", predictor = "am") %>% stats::model.frame()
#> mpg am
#> Mazda RX4 21.0 1
#> Mazda RX4 Wag 21.0 1
#> Datsun 710 22.8 1
#> Hornet 4 Drive 21.4 0
#> Hornet Sportabout 18.7 0
#> Valiant 18.1 0
#> Duster 360 14.3 0
#> Merc 240D 24.4 0
#> Merc 230 22.8 0
#> Merc 280 19.2 0
#> Merc 280C 17.8 0
#> Merc 450SE 16.4 0
#> Merc 450SL 17.3 0
#> Merc 450SLC 15.2 0
#> Cadillac Fleetwood 10.4 0
#> Lincoln Continental 10.4 0
#> Chrysler Imperial 14.7 0
#> Fiat 128 32.4 1
#> Honda Civic 30.4 1
#> Toyota Corolla 33.9 1
#> Toyota Corona 21.5 0
#> Dodge Challenger 15.5 0
#> AMC Javelin 15.2 0
#> Camaro Z28 13.3 0
#> Pontiac Firebird 19.2 0
#> Fiat X1-9 27.3 1
#> Porsche 914-2 26.0 1
#> Lotus Europa 30.4 1
#> Ford Pantera L 15.8 1
#> Ferrari Dino 19.7 1
#> Maserati Bora 15.0 1
#> Volvo 142E 21.4 1
####
####
####
# scenario B -- working
my_lm_built_in_formula_via_pipe <- function(.dat, predicted, predictor){
.dat %>%
select(my_predicted = {{ predicted }}, my_predictor = {{ predictor }}) %>%
lm(my_predicted ~ my_predictor, data = .)
}
## both calls work:
my_lm_built_in_formula_via_pipe(.dat = mtcars, predicted = "mpg", predictor = "am") %>% effectsize()
#> # Standardization method: refit
#>
#> Parameter | Coefficient (std.) | 95% CI
#> -------------------------------------------------
#> (Intercept) | 2.94e-17 | [-0.29, 0.29]
#> my_predictor | 0.60 | [ 0.30, 0.90]
my_lm_built_in_formula_via_pipe(.dat = mtcars, predicted = "mpg", predictor = "am") %>% stats::model.frame()
#> my_predicted my_predictor
#> Mazda RX4 21.0 1
#> Mazda RX4 Wag 21.0 1
#> Datsun 710 22.8 1
#> Hornet 4 Drive 21.4 0
#> Hornet Sportabout 18.7 0
#> Valiant 18.1 0
#> Duster 360 14.3 0
#> Merc 240D 24.4 0
#> Merc 230 22.8 0
#> Merc 280 19.2 0
#> Merc 280C 17.8 0
#> Merc 450SE 16.4 0
#> Merc 450SL 17.3 0
#> Merc 450SLC 15.2 0
#> Cadillac Fleetwood 10.4 0
#> Lincoln Continental 10.4 0
#> Chrysler Imperial 14.7 0
#> Fiat 128 32.4 1
#> Honda Civic 30.4 1
#> Toyota Corolla 33.9 1
#> Toyota Corona 21.5 0
#> Dodge Challenger 15.5 0
#> AMC Javelin 15.2 0
#> Camaro Z28 13.3 0
#> Pontiac Firebird 19.2 0
#> Fiat X1-9 27.3 1
#> Porsche 914-2 26.0 1
#> Lotus Europa 30.4 1
#> Ford Pantera L 15.8 1
#> Ferrari Dino 19.7 1
#> Maserati Bora 15.0 1
#> Volvo 142E 21.4 1
由 reprex package (v2.0.0)
于 2021-08-15 创建知道为什么我在场景 A 中出现错误(但在场景 B 中没有),以及为什么 effectsize()
失败而 stats::model.frame()
没有?
当您将 lm 对象传递给 effectsize() 时,它会在您当前的 R 环境中重新评估调用,而不是在创建公式变量的环境中,因此它会抛出错误,因为它找不到 my_formula
对于stats::model.frame
,因为你已经传递了lm对象,它只是拉出模型矩阵,不需要评估,你可以尝试传递它的公式:
x_formula <- function(.dat, predicted, predictor){
my_formula <- as.formula(paste0(predicted, "~", predictor))
my_formula
}
x_formula(.dat = mtcars,"am","gear") %>% stats::model.frame(data=mtcars)
Error in x_formula(.dat = mtcars, "am", "gear") :
could not find function "x_formula"
你可以看到它也失败了。所以这是一个错误的比较。
您可以强制计算调用,参见 this book chapter,但我不太确定这样做是否正确:
my_lm_external_formula <- function(.dat, predicted, predictor){
f = reformulate(response=predictor,termlabels=predicted)
fit = lm(f, data = .dat)
fit$call$formula = eval(f)
fit
}
my_lm_external_formula(.dat = mtcars, predicted = "mpg", predictor = "am") %>%
effectsize()
# Standardization method: refit
Parameter | Coefficient (std.) | 95% CI
------------------------------------------------
(Intercept) | -1.77e-17 | [-0.29, 0.29]
mpg | 0.60 | [ 0.30, 0.90]
您经常 运行 涉及 lm
的范围问题和 lm 对象的方法。我在使用该语言进行计算方面有很好的经验,但我不能保证您永远不会 运行 遇到问题。那里有一些方法不适用于尚未在与其调用相同的环境中创建的 lm 对象,一些不好的方法甚至需要在全局环境中创建它。
my_lm_external_formula <- function(.dat, predicted, predictor){
predicted <- as.name(predicted)
predictor <- as.name(predictor)
eval(bquote(lm(formula = .(predicted) ~ .(predictor), data = .dat)))
}
effectsize(
my_lm_external_formula(.dat = mtcars,
predicted = "mpg",
predictor = "am")
)
#works