r语言 - rstudent()返回AN"的结果不正确的结果.(带有多个LHS的线性模型)



我知道对具有多个LHS的线性模型的支持是有限的。但是,如果可以在" MLM"对象上运行功能时,我希望结果值得信赖。使用rstudent时,会产生奇怪的结果。这是一个错误还是还有其他解释?

fittedAfittedB下的示例中是相同的,但在rstudent的情况下,第二列有所不同。

y <- matrix(rnorm(20), 10, 2)
x <- 1:10
fittedA <- fitted(lm(y ~ x))
fittedB <- cbind(fitted(lm(y[, 1] ~ x)), fitted(lm(y[, 2] ~ x)))
rstudentA <- rstudent(lm(y ~ x))
rstudentB <- cbind(rstudent(lm(y[, 1] ~ x)), rstudent(lm(y[, 2] ~ x)))

设置

set.seed(0)
y <- matrix(rnorm(20), 10, 2)
x <- 1:10
fit <- lm(y ~ x)           ## class: "mlm", "lm"
fit1 <- lm(y[, 1] ~ x)     ## class: "lm"
fit2 <- lm(y[, 2] ~ x)     ## class: "lm"
rstudent(fit)
#          [,1]        [,2]
#1   0.74417620  0.89121744
#2  -0.67506054 -0.50275275
#3   0.76297805 -0.74363941
#4   0.71164461  0.01075898
#5   0.03337192  0.03355209
#6  -1.75099724 -0.02701558
#7  -1.05594284  0.56993056
#8  -0.48486883 -0.35286612
#9  -0.23468552  0.79610101
#10  2.90701182 -0.93665406
cbind(rstudent(fit1), rstudent(fit2))
#          [,1]        [,2]
#1   0.74417620  1.90280959
#2  -0.67506054 -0.92973971
#3   0.76297805 -1.47237918
#4   0.71164461  0.01870820
#5   0.03337192  0.06042497
#6  -1.75099724 -0.04056992
#7  -1.05594284  1.02171222
#8  -0.48486883 -0.64316472
#9  -0.23468552  1.69605079
#10  2.90701182 -1.25676088

正如您所观察到的,仅rstandard(fit)正确返回了第一个响应的结果。


为什么rstudent在" MLM"上失败

事实是,rstudent没有" MLM"方法。

methods(rstudent)
#[1] rstudent.glm* rstudent.lm*

调用rstudent(fit)时,S3方法调度机制会找到rstudent.lm,因为inherits(fit, "lm")TRUE。不幸的是,stats:::rstudent.lm没有为" MLM"模型进行正确的计算。

stats:::rstudent.lm
#function (model, infl = lm.influence(model, do.coef = FALSE), 
#    res = infl$wt.res, ...) 
#{
#    res <- res/(infl$sigma * sqrt(1 - infl$hat))
#    res[is.infinite(res)] <- NaN
#    res
#}

lm.influence不给" MLM"给出正确的sigma。基础C例程C_influence仅计算" LM"的sigma。如果您给lm.influence一个" MLM",则仅返回第一个响应变量的结果。

## pass in "mlm"
.Call(stats:::C_influence, fit$qr, FALSE, residuals(fit), 10 * .Machine$double.eps)$sigma
# [1] 1.3130265 1.3216357 1.3105706 1.3171621 1.3638689 1.1374385 1.2668101
# [8] 1.3416338 1.3586428 0.9180828
## pass in "lm"
.Call(stats:::C_influence, fit1$qr, FALSE, residuals(fit1), 10 * .Machine$double.eps)$sigma
# [1] 1.3130265 1.3216357 1.3105706 1.3171621 1.3638689 1.1374385 1.2668101
# [8] 1.3416338 1.3586428 0.9180828

显然,对于" MLM",sigma应该是矩阵。现在给定此不正确的sigma,"回收规则"在以下stats:::rstudent.lm行的"/"后面应用,因为res(残差)左侧是矩阵,但其右边的内容是矢量。

res <- res / (infl$sigma * sqrt(1 - infl$hat))

有效地,计算结果仅适用于第一个响应变量。其余的响应变量将使用错误的sigma


R核心团队需要修补许多诊断功能

请注意,文档页面?influence.measures中列出的几乎所有功能都是" MLM"的错误。他们应该发出警告,称" MLM"方法尚未实施。

lm.influnce需要在C级修补。完成此操作后,rstudent.lm将在" MLM"上正确工作。

OHTER功能可以在R级上轻松修补,例如stats:::cooks.distance.lmstats:::rstandard。目前(r 3.5.1)它们是:

stats:::cooks.distance.lm
#function (model, infl = lm.influence(model, do.coef = FALSE), 
#    res = weighted.residuals(model),
#    sd = sqrt(deviance(model)/df.residual(model)), 
#    hat = infl$hat, ...) 
#{
#    p <- model$rank
#    res <- ((res/(sd * (1 - hat)))^2 * hat)/p
#    res[is.infinite(res)] <- NaN
#    res
#}
stats:::rstandard.lm
#function (model, infl = lm.influence(model, do.coef = FALSE), 
#    sd = sqrt(deviance(model)/df.residual(model)), type = c("sd.1", 
#        "predictive"), ...) 
#{
#    type <- match.arg(type)
#    res <- infl$wt.res/switch(type, sd.1 = sd * sqrt(1 - infl$hat), 
#        predictive = 1 - infl$hat)
#    res[is.infinite(res)] <- NaN
#    res
#}

可以用

对其进行修补(使用outer
patched_cooks.distance.lm <-
function (model, infl = lm.influence(model, do.coef = FALSE), 
    res = weighted.residuals(model),
    sd = sqrt(deviance(model)/df.residual(model)), 
    hat = infl$hat, ...) 
{
    p <- model$rank
    res <- ((res / c(outer(1 - hat, sd))) ^ 2 * hat) / p
    res[is.infinite(res)] <- NaN
    res
}
patched_rstandard.lm <- 
function (model, infl = lm.influence(model, do.coef = FALSE), 
    sd = sqrt(deviance(model)/df.residual(model)), type = c("sd.1", 
        "predictive"), ...) 
{
    type <- match.arg(type)
    res <- infl$wt.res/switch(type, sd.1 = c(outer(sqrt(1 - infl$hat), sd)), 
        predictive = 1 - infl$hat)
    res[is.infinite(res)] <- NaN
    res
}

快速测试:

oo <- cbind(cooks.distance(fit1), cooks.distance(fit2))  ## correct result
all.equal(cooks.distance(fit), oo)
#[1] "Mean relative difference: 0.8211302"
all.equal(patched_cooks.distance.lm(fit), oo)
#[1] TRUE
rr <- cbind(rstandard(fit1), rstandard(fit2))  ## correct result
all.equal(rstandard(fit), rr)
#[1] "Mean relative difference: 0.5290036"
all.equal(patched_rstandard.lm(fit), rr)
#[1] TRUE

谢谢 @李哲源;另请参阅https://www.r-project.org/bugs.html有关如何报告错误... R Core Team会更好地注意到它们。另外,在那里,我们可以更好地对补丁给予更好的信用。
ALS注意,R的源代码 - 尤其是它的开发版本 - 始终可通过SVN(" subversion")或https://svn.r-project.org/r/r/trunk/

提供。

cooks.distance.lm()'s和 rstandard.lm()的源代码都在https://svn.r-project.org/r/trunk/src/library/stats/r/l/m.influence.r ....下一次。您提出的通过outer()更改的小型代码当然已经足够好。

非常感谢您进行彻底的分析以及您建议的错误修复!

相关内容

  • 没有找到相关文章

最新更新