正如 cmets 中所建议的,一种直接的方法是使用第一次拟合的 model 数据(例如 probit)和 update 覆盖原始调用中的参数的能力。
这是一个可重现的例子:
data(mtcars)
mtcars[1,2] <- NA
nobs( xa <- lm(mpg~cyl+disp, mtcars) )
## [1] 31
nobs( update(xa, .~.-cyl) ) ##not nested
## [1] 32
nobs( xb <- update(xa, .~.-cyl, data=xa$model) ) ##nested
## [1] 31
围绕它定义一个方便的包装器很容易:
update_nested <- function(object, formula., ..., evaluate = TRUE){
update(object = object, formula. = formula., data = object$model, ..., evaluate = evaluate)
}
这会强制更新调用的 data 参数重新使用来自第一个模型拟合的数据。
nobs( xc <- update_nested(xa, .~.-cyl) )
## [1] 31
all.equal(xb, xc) ##only the `call` component will be different
## [1] "Component “call”: target, current do not match when deparsed"
identical(xb[-10], xc[-10])
## [1] TRUE
所以现在你可以轻松做到anova:
anova(xa, xc)
## Analysis of Variance Table
##
## Model 1: mpg ~ cyl + disp
## Model 2: mpg ~ disp
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 28 269.97
## 2 29 312.96 -1 -42.988 4.4584 0.04378 *
## ---
## Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
建议的另一种方法是na.omit 在lm() 调用之前的数据帧上。起初,我认为这在处理大数据帧(例如 1000 列)和各种规格的大量变量(例如 ~15 个变量)时是不切实际的,但不是因为速度。这种方法需要手动记账哪些 vars 应该对 NA 进行清理,哪些不应该,这正是 OP 似乎打算避免的。最大的缺点是您必须始终使formula 与子集数据帧保持同步。
然而,事实证明,这很容易克服:
data(mtcars)
for(i in 1:ncol(mtcars)) mtcars[i,i] <- NA
nobs( xa <- lm(mpg~cyl + disp + hp + drat + wt + qsec + vs + am + gear +
carb, mtcars) )
## [1] 21
nobs( xb <- update(xa, .~.-cyl) ) ##not nested
## [1] 22
nobs( xb <- update_nested(xa, .~.-cyl) ) ##nested
## [1] 21
nobs( xc <- update(xa, .~.-cyl, data=na.omit(mtcars[ , all.vars(formula(xa))])) ) ##nested
## [1] 21
all.equal(xb, xc)
## [1] "Component “call”: target, current do not match when deparsed"
identical(xb[-10], xc[-10])
## [1] TRUE
anova(xa, xc)
## Analysis of Variance Table
##
## Model 1: mpg ~ cyl + disp + hp + drat + wt + qsec + vs + am + gear + carb
## Model 2: mpg ~ disp + hp + drat + wt + qsec + vs + am + gear + carb
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 10 104.08
## 2 11 104.42 -1 -0.34511 0.0332 0.8591