plot.lm Error: $ operator is invalid for atomic vectors

plot.lm Error: $ operator is invalid for atomic vectors

我有以下带转换的回归模型:

fit <- lm( I(NewValue ^ (1 / 3)) ~ I(CurrentValue ^ (1 / 3)) + Age + Type - 1,
           data = dataReg)
plot(fit)                                                                      

但是 plot 给我以下错误:

Error: $ operator is invalid for atomic vectors

关于我做错了什么有什么想法吗?

注意summarypredictresiduals 都可以正常工作。

这实际上是一个非常有趣的观察。事实上,在 plot.lm 支持的所有 6 个图中,只有 Q-Q 图在这种情况下失败了。考虑以下可重现的示例:

x <- runif(20)
y <- runif(20)
fit <- lm(I(y ^ (1/3)) ~ I(x ^ (1/3)))
## only `which = 2L` (QQ plot) fails; `which = 1, 3, 4, 5, 6` all work
stats:::plot.lm(fit, which = 2L)

里面plot.lm简单的Q-Q图制作如下:

rs <- rstandard(fit)  ## standardised residuals
qqnorm(rs)  ## fine
## inside `qqline(rs)`
yy <- quantile(rs, c(0.25, 0.75))
xx <- qnorm(c(0.25, 0.75))
slope <- diff(yy)/diff(xx)
int <- yy[1L] - slope * xx[1L]
abline(int, slope)  ## this fails!!!

Error: $ operator is invalid for atomic vectors

所以这纯粹是abline函数的问题!注:

is.object(int)
# [1] TRUE

is.object(slope)
# [1] TRUE

intslope都具有class属性(读取?is.object;这是一种非常有效的检查对象是否具有 class 属性 )。什么class?

class(int)
# [1] AsIs

class(slope)
# [1] AsIs

这是使用I()的结果。准确地说,他们从 rs 继承了这样的 class,并进一步继承了响应变量。也就是说,如果我们在响应中使用 I(),即模型公式的 RHS,我们就会得到这种行为。

你可以在这里做一些实验:

abline(as.numeric(int), as.numeric(slope))  ## OK
abline(as.numeric(int), slope)  ## OK
abline(int, as.numeric(slope))  ## fails!!
abline(int, slope)  ## fails!!

所以abline(a, b)对第一个参数a是否有class属性很敏感

为什么?因为abline可以接受"lm"class的线性模型对象。里面 abline:

if (is.object(a) || is.list(a)) {
    p <- length(coefa <- as.vector(coef(a)))

如果a有一个class,abline假设它是一个模型对象(不管它是否真的是!!!),然后尝试使用 coef 获取系数。此处进行的检查相当不可靠;我们可以很容易地让 abline 失败:

plot(0:1, 0:1)
a <- 0  ## plain numeric
abline(a, 1)  ## OK
class(a) <- "whatever"  ## add a class
abline(a, 1)  ## oops, fails!!!

Error: $ operator is invalid for atomic vectors

所以这里是结论:避免在模型公式中的响应变量上使用 I() 在协变量上使用 I() 是可以的,但没有回应。 lm 和大多数通用函数处理此问题不会有问题,但 plot.lm 会。