这实际上是一个非常有趣的观察结果。事实上,在plot.lm
支持的所有6个图中,只有Q-Q图在这种情况下失败了。考虑以下可复制的示例:
x <- runif(20)
y <- runif(20)
fit <- lm(I(y ^ (1/3)) ~ I(x ^ (1/3)))
stats:::plot.lm(fit, which = 2L)
在plot.lm
函数内部,Q-Q图可以简单地通过以下方式生成:
rs <- rstandard(fit)
qqnorm(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)
错误:$ 操作符对于原子向量无效
因此,这完全是 abline
函数的问题! 注意:
is.object(int)
is.object(slope)
即,
int
和
slope
都有 class 属性(
阅读 ?is.object
;这是一种非常有效的检查对象是否有 class 属性的方法)。那么它们属于哪个 class?
class(int)
class(slope)
这是使用
I()
的结果。准确地说,它们从
rs
类继承,进一步从响应变量继承。也就是说,如果我们在模型公式的 RHS 上使用
I()
,就会得到这种行为。
你可以在这里进行一些实验:
abline(as.numeric(int), as.numeric(slope))
abline(as.numeric(int), slope)
abline(int, as.numeric(slope))
abline(int, slope)
因此,abline(a, b)
非常敏感于第一个参数a
是否具有类属性。
为什么?因为abline
可以接受具有“lm”类的线性模型对象。在abline
内部:
if (is.object(a) || is.list(a)) {
p <- length(coefa <- as.vector(coef(a)))
如果a
有一个类,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!!!
错误:原子向量无效的$操作符
因此,结论是:在模型公式中避免在响应变量上使用I()
。 在协变量上使用I()
是可以的,但在响应变量上使用不行。 lm
和大多数通用函数处理这个问题不会有麻烦,但plot.lm
会出现问题。
summary fit
吗? - Christoph