在 R 中,通过函数拟合线性最小二乘模型lm()
。使用公式接口我们可以使用subset
参数来选择用于拟合实际模型的数据点,例如:
lin <- data.frame(x = c(0:6), y = c(0.3, 0.1, 0.9, 3.1, 5, 4.9, 6.2))
linm <- lm(y ~ x, data = lin, subset = 2:4)
给予:
R> linm
Call:
lm(formula = y ~ x, data = lin, subset = 2:4)
Coefficients:
(Intercept) x
-1.633 1.500
R> fitted(linm)
2 3 4
-0.1333333 1.3666667 2.8666667
至于双对数,我猜你有两个选择;i) 像我们上面所做的那样估计两个单独的模型,或 ii) 通过 ANCOVA 估计。对数转换在公式中使用log()
.
通过两个独立的模型:
logm1 <- lm(log(y) ~ log(x), data = dat, subset = 1:7)
logm2 <- lm(log(y) ~ log(x), data = dat, subset = 8:15)
或者通过 ANCOVA,我们需要一个指示变量
dat <- transform(dat, ind = factor(1:15 <= 7))
logm3 <- lm(log(y) ~ log(x) * ind, data = dat)
您可能会问这两种方法是否等效?好吧,我们可以通过模型系数来证明这一点。
R> coef(logm1)
(Intercept) log(x)
-0.0001487042 -0.4305802355
R> coef(logm2)
(Intercept) log(x)
0.1428293 -1.4966954
因此,对于单独的模型,两个斜率分别为 -0.4306 和 -1.4967。ANCOVA 模型的系数为:
R> coef(logm3)
(Intercept) log(x) indTRUE log(x):indTRUE
0.1428293 -1.4966954 -0.1429780 1.0661152
我们如何调和两者?好吧,我设置的方式ind
是logm3
参数化的,以提供更直接的估计值logm2
;logm2
和的截距logm3
相同, 的系数也相同log(x)
。为了得到与 的系数相等的值logm1
,我们需要进行操作,首先是截距:
R> coefs[1] + coefs[3]
(Intercept)
-0.0001487042
其中系数为indTRUE
第 1 组的平均值与第 2 组的平均值之差。对于斜率:
R> coefs[2] + coefs[4]
log(x)
-0.4305802
这与我们得到的相同,logm1
并且基于第 2 组 ( ) 的coefs[2]
斜率,由第 1 组 ( ) 的斜率差异修改coefs[4]
。
至于绘图,一个简单的方法是通过abline()
简单模型。例如对于普通数据示例:
plot(y ~ x, data = lin)
abline(linm)
对于日志数据,我们可能需要更有创意,这里的一般解决方案是预测数据范围并绘制预测:
pdat <- with(dat, data.frame(x = seq(from = head(x, 1), to = tail(x,1),
by = 0.1))
pdat <- transform(pdat, yhat = c(predict(logm1, pdat[1:70,, drop = FALSE]),
predict(logm2, pdat[71:141,, drop = FALSE])))
它可以通过取幂在原始比例上绘制yhat
plot(y ~ x, data = dat)
lines(exp(yhat) ~ x, dat = pdat, subset = 1:70, col = "red")
lines(exp(yhat) ~ x, dat = pdat, subset = 71:141, col = "blue")
或对数刻度:
plot(log(y) ~ log(x), data = dat)
lines(yhat ~ log(x), dat = pdat, subset = 1:70, col = "red")
lines(yhat ~ log(x), dat = pdat, subset = 71:141, col = "blue")
例如...
这种通用解决方案也适用于更复杂的 ANCOVA 模型。在这里我像以前一样创建一个新的 pdat 并添加一个指标
pdat <- with(dat, data.frame(x = seq(from = head(x, 1), to = tail(x,1),
by = 0.1)[1:140],
ind = factor(rep(c(TRUE, FALSE), each = 70))))
pdat <- transform(pdat, yhat = predict(logm3, pdat))
predict()
请注意,由于使用 ANCOVA to fit ,我们如何从单个调用中获得我们想要的所有预测logm3
。我们现在可以像以前一样绘制:
plot(y ~ x, data = dat)
lines(exp(yhat) ~ x, dat = pdat, subset = 1:70, col = "red")
lines(exp(yhat) ~ x, dat = pdat, subset = 71:141, col = "blue")