这个答案会有点像百科全书,因为关于你的问题有几个要点。 tl;dr作为随机效应添加year*plot
是第一步,但拟合实际上有点问题,虽然起初看起来不是这样:使year
变量居中可以解决问题,但是对数据进行对数转换可能是更好的主意。
更新: OP 正在对subset(df,Depth==30)
. 我不小心对整个数据集进行了分析,这可能使事情变得更加困难——下面记录的异方差性对于数据的子集可能并没有那么糟糕——但出于教学目的,我将保持原样(出于懒惰)。
获取数据:
df <- read.csv("rootmeansv2.csv")
library(nlme)
gdf <- groupedData( mass ~ year | plot, data=df)
将逐年的交互作为随机效应添加到模型中:
fit0 <- lme(mass ~ year , random = ~ year | plot, data = gdf)
但是,如果我们查看结果,我们会发现这根本没有多大帮助——这个year
项(斜率中的绘图方差)很小。
## Variance StdDev Corr
## (Intercept) 9.522880e-12 3.085916e-06 (Intr)
## year 7.110616e-08 2.666574e-04 0.32
## Residual 3.885373e-01 6.233276e-01
有时确实会发生这种情况(单数拟合),但除此之外,lme
摘要不会以任何其他方式表明可能存在问题。但是,如果我们尝试获得置信区间,我们会发现可能会有问题:
intervals(fit0)
## Error in intervals.lme(fit0) :
## cannot get confidence intervals on var-cov components: Non-positive definite approximate variance-covariance
仔细检查的另一种方法是在lme4
.
library(lme4)
VarCorr(fit1 <- lmer(mass ~ year +(year | plot), data = gdf))
## Groups Name Std.Dev. Corr
## plot (Intercept) 0.66159674
## year 0.00059471 -1.000
## Residual 0.62324403
## Warning messages:
## 1: In checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
## Model failed to converge with max|grad| = 0.132739 (tol = 0.002, component 1)
## 2: In checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
## Model failed to converge: degenerate Hessian with 1 negative eigenvalues
我们得到了明显不同的答案,以及关于收敛的警告(这是在开发版本 1.1-7 中,它不受 1.1-6 广泛报道的误报警告的影响)。看起来lme4
' 的合身性稍好一些:
c(logLik(fit1)-logLik(fit0))
## 0.1775161
复杂拟合(例如混合模型)的潜在数据问题之一是预测变量的中心化和缩放不良。在这种情况下,因为year
是从 2008 年开始的连续预测变量,所以截距和斜率高度相关(截距是第 0 年的预测值!)。在这种情况下,我们可以通过居中解决问题——减去最小值也是合理的(即从 0 开始年份而不是 2008 年)
c. <- function(x) scale(x,center=TRUE,scale=FALSE)
VarCorr(fit2 <- update(fit1,.~ c.(year) +(c.(year) | plot)))
## Groups Name Std.Dev. Corr
## plot (Intercept) 0.53798
## c.(year) 0.10515 1.000
## Residual 0.59634
我们得到了更合理的答案(并且没有警告),尽管我们仍然有完全(现在正)相关的截距和斜率——这只是说模型稍微过度拟合了数据,但我们对此无能为力(我们可以通过拟合模型将相关性强制为零~c.(year)+(c.(year)||plot))
,但这有其自身的问题)。
现在试试lme
:
VarCorr(fit3 <- update(fit0,
fixed.=~c.(year),
random=~c.(year)|plot,
control=lmeControl(opt="optim")))
## plot = pdLogChol(c.(year))
## Variance StdDev Corr
## (Intercept) 0.28899909 0.5375864 (Intr)
## c.(year) 0.01122497 0.1059479 0.991
## Residual 0.35559015 0.5963138
结果相似(尽管相关性仅为 0.991 而不是 1.0):对数似然的差异实际上略大,但仍然很小。(拟合仍然有些问题——我必须更改优化器,如lmeControl
参数所示才能到达这里。)
现在看起来好多了:
plot(augPred(fit3))

但是,残差与拟合图向您展示了一个您应该担心的问题:
plot(fit3)

漏斗形状表明您存在异方差问题。比例位置图更清楚地显示了它:
plot(fit3,sqrt(abs(resid(.)))~fitted(.),type=c("p","smooth"))

最明显的解决方法是对数据进行日志转换:
df$logmass <- log10(df$mass) ## log10() for interpretability
gdfL <- groupedData( logmass ~ year | plot, data=df)
VarCorr(fitL1 <- lme(logmass ~ c.(year) , random = ~ c.(year) | plot,
data = gdfL))
## plot = pdLogChol(c.(year))
## Variance StdDev Corr
## (Intercept) 0.1842905872 0.42929080 (Intr)
## c.(year) 0.0009702893 0.03114947 -0.607
## Residual 0.1052946948 0.32449144
年际变化又小了,但这一次可能是因为不需要。lmer
当我们拟合等效模型时没有警告,并且我们得到相同的结果;拟合是非奇异的(没有零方差或完全相关);和intervals(fitL1)
作品。
预测看起来很合理:
plot(augPred(fitL1))

诊断图也是如此:
plot(fitL1)

尽管 2008 年似乎确实有些有趣(轴被翻转是因为lme
更喜欢水平绘制箱线图——factor(year)
告诉lme
使用箱线图而不是散点图)。
plot(fitL1,factor(year)~resid(.))
