Data

setwd(getwd())
dataMA <- read.csv("TableS1_R.csv", sep = ";", header = TRUE) 
sitedat <- dataMA[!duplicated(dataMA$Site_Number),] # Datatable with 52 rows, one per site
LoEsc <- as.numeric(as.character(recode(dataMA$Level_of_Evidence,"'LoE3a'=3;'LoE3b'=3.3;'LoE4a'=4;'LoE4b'=4.3")))
dataMA$Forest_Composition <- factor(dataMA$Forest_Composition,levels = c("Con","Mix","Dec"))
dataMA_new <- data.frame(dataMA,LoEsc)

Effect sizes

Effect sizes are already included in the data file, but for a matter of clarity, we show how they were calculated and demonstrate that they are the same than those included in the data file.

es <- escalc(measure="SMD",m1i=MT,sd1i=ST,n1i=NT,m2i=MC,sd2i=SC,n2i=NC,data=dataMA_new) 
table(round(es$yi,digits=2)==es$Effect_Size)
## 
## TRUE 
##  348
table(round(es$vi,digits=2)==es$Variance_of_Effect_Size)
## 
## TRUE 
##  348

Figure 1

Standardized mean difference of stream nitrate concentrations plotted against post-harvest time series. Colours reflect the different harvest types. Most long-term studies were clearcut treatments. Only seven studies had records for more than fifteen years after harvest.

Meta-analytical model

Model selection based on ANOVA (F-Statistic)

Step-wise reduction of predictors based on a Wald F-test

fullmodel <- lme(yi~Forest_Harvest+Forest_Composition+Time_after_harvest+Catchment_Size+Forest_Age+
                   Mean_Annual_Temperature+Mean_Annual_Precipitation+Altitude+Harvest_Year,
             random=~1+Time_after_harvest|Site_Number,
             weights=varFixed(~(vi*LoEsc)),
             control=list(sigma=1),
             correlation=corCAR1(form=~Time_after_harvest|Site_Number),
             method="ML",
             data=es)
anova(fullmodel)
##                           numDF denDF  F-value p-value
## (Intercept)                   1   295 60.95516  <.0001
## Forest_Harvest                4    39  4.92755  0.0026
## Forest_Composition            2    39  8.92327  0.0006
## Time_after_harvest            1   295 17.32069  <.0001
## Catchment_Size                1    39  0.02904  0.8656
## Forest_Age                    1    39  0.48636  0.4897
## Mean_Annual_Temperature       1    39  0.00049  0.9825
## Mean_Annual_Precipitation     1    39  0.23223  0.6326
## Altitude                      1    39 17.94309  0.0001
## Harvest_Year                  1    39  0.06765  0.7962
anova(update(fullmodel,~.-Mean_Annual_Temperature))
##                           numDF denDF  F-value p-value
## (Intercept)                   1   295 60.58795  <.0001
## Forest_Harvest                4    40  4.89894  0.0026
## Forest_Composition            2    40  8.92063  0.0006
## Time_after_harvest            1   295 17.43049  <.0001
## Catchment_Size                1    40  0.03092  0.8613
## Forest_Age                    1    40  0.46945  0.4972
## Mean_Annual_Precipitation     1    40  0.21636  0.6444
## Altitude                      1    40 18.00338  0.0001
## Harvest_Year                  1    40  0.05975  0.8081
anova(update(fullmodel,~.-Mean_Annual_Temperature-Harvest_Year))
##                           numDF denDF  F-value p-value
## (Intercept)                   1   295 60.51389  <.0001
## Forest_Harvest                4    41  4.89104  0.0026
## Forest_Composition            2    41  8.92092  0.0006
## Time_after_harvest            1   295 17.43002  <.0001
## Catchment_Size                1    41  0.03145  0.8601
## Forest_Age                    1    41  0.46621  0.4986
## Mean_Annual_Precipitation     1    41  0.21447  0.6457
## Altitude                      1    41 18.02031  0.0001
anova(update(fullmodel,~.-Mean_Annual_Temperature-Harvest_Year-Catchment_Size))
##                           numDF denDF  F-value p-value
## (Intercept)                   1   295 61.75428  <.0001
## Forest_Harvest                4    42  4.98649  0.0022
## Forest_Composition            2    42  8.99249  0.0006
## Time_after_harvest            1   295 17.29220  <.0001
## Forest_Age                    1    42  0.49495  0.4856
## Mean_Annual_Precipitation     1    42  0.22289  0.6393
## Altitude                      1    42 17.51613  0.0001
anova(update(fullmodel,~.-Mean_Annual_Temperature-Harvest_Year-Catchment_Size-Mean_Annual_Precipitation))
##                    numDF denDF  F-value p-value
## (Intercept)            1   295 62.65931  <.0001
## Forest_Harvest         4    43  5.05354  0.0020
## Forest_Composition     2    43  9.04175  0.0005
## Time_after_harvest     1   295 17.32483  <.0001
## Forest_Age             1    43  0.52504  0.4726
## Altitude               1    43 17.60566  0.0001
anova(update(fullmodel,~.-Mean_Annual_Temperature-Harvest_Year-Catchment_Size-Mean_Annual_Precipitation-Forest_Age))
##                    numDF denDF  F-value p-value
## (Intercept)            1   295 55.58098  <.0001
## Forest_Harvest         4    44  4.45334  0.0041
## Forest_Composition     2    44  8.50799  0.0008
## Time_after_harvest     1   295 18.31443  <.0001
## Altitude               1    44 16.85916  0.0002

Model selection based on Akaike Information Criterion (AIC)

#Forward selection
emptymodel <- update(fullmodel,~.-.)
stepAIC(emptymodel,~Forest_Harvest+Forest_Composition+Time_after_harvest+Catchment_Size+Forest_Age+
          Mean_Annual_Temperature+Mean_Annual_Precipitation+Altitude+Harvest_Year,direction="forward")
## Start:  AIC=959.53
## yi ~ 1
## 
##                             Df    AIC
## + Time_after_harvest         1 948.77
## + Forest_Composition         2 950.36
## + Forest_Harvest             4 957.50
## + Altitude                   1 959.17
## <none>                         959.53
## + Mean_Annual_Temperature    1 959.96
## + Mean_Annual_Precipitation  1 960.66
## + Catchment_Size             1 960.87
## + Harvest_Year               1 961.01
## + Forest_Age                 1 961.06
## 
## Step:  AIC=948.77
## yi ~ Time_after_harvest
## 
##                             Df    AIC
## + Forest_Composition         2 939.94
## + Altitude                   1 946.99
## + Forest_Harvest             4 947.30
## <none>                         948.77
## + Mean_Annual_Temperature    1 949.57
## + Catchment_Size             1 950.28
## + Mean_Annual_Precipitation  1 950.39
## + Harvest_Year               1 950.63
## + Forest_Age                 1 950.76
## 
## Step:  AIC=939.94
## yi ~ Time_after_harvest + Forest_Composition
## 
##                             Df    AIC
## + Forest_Harvest             4 937.62
## + Altitude                   1 937.72
## <none>                         939.94
## + Forest_Age                 1 941.74
## + Mean_Annual_Precipitation  1 941.75
## + Harvest_Year               1 941.81
## + Mean_Annual_Temperature    1 941.86
## + Catchment_Size             1 941.86
## 
## Step:  AIC=937.62
## yi ~ Time_after_harvest + Forest_Composition + Forest_Harvest
## 
##                             Df    AIC
## + Altitude                   1 925.47
## <none>                         937.62
## + Harvest_Year               1 938.85
## + Forest_Age                 1 938.94
## + Mean_Annual_Precipitation  1 939.53
## + Mean_Annual_Temperature    1 939.60
## + Catchment_Size             1 939.60
## 
## Step:  AIC=925.47
## yi ~ Time_after_harvest + Forest_Composition + Forest_Harvest + 
##     Altitude
## 
##                             Df    AIC
## <none>                         925.47
## + Forest_Age                 1 926.11
## + Catchment_Size             1 927.05
## + Mean_Annual_Precipitation  1 927.06
## + Harvest_Year               1 927.31
## + Mean_Annual_Temperature    1 927.33
## Linear mixed-effects model fit by maximum likelihood
##   Data: es 
##   Log-likelihood: -449.7329
##   Fixed: yi ~ Time_after_harvest + Forest_Composition + Forest_Harvest +      Altitude 
##                  (Intercept)           Time_after_harvest 
##                  0.516107070                 -0.106404194 
##        Forest_CompositionMix        Forest_CompositionDec 
##                 -0.777111243                  0.721912517 
##  Forest_Harvestpatchcut-high   Forest_Harvestpatchcut-low 
##                 -0.192602990                  0.232387374 
## Forest_Harvestselective-high  Forest_Harvestselective-low 
##                 -1.200503899                 -1.679633414 
##                     Altitude 
##                  0.001878778 
## 
## Random effects:
##  Formula: ~1 + Time_after_harvest | Site_Number
##  Structure: General positive-definite, Log-Cholesky parametrization
##                    StdDev     Corr  
## (Intercept)        0.64950485 (Intr)
## Time_after_harvest 0.09474031 -0.071
## Residual           1.00000000       
## 
## Correlation Structure: Continuous AR(1)
##  Formula: ~Time_after_harvest | Site_Number 
##  Parameter estimate(s):
##       Phi 
## 0.4251468 
## Variance function:
##  Structure: fixed weights
##  Formula: ~(vi * LoEsc) 
## Number of Observations: 348
## Number of Groups: 52
#Backward selection
stepAIC(fullmodel) 
## Start:  AIC=933.48
## yi ~ Forest_Harvest + Forest_Composition + Time_after_harvest + 
##     Catchment_Size + Forest_Age + Mean_Annual_Temperature + Mean_Annual_Precipitation + 
##     Altitude + Harvest_Year
## 
##                             Df    AIC
## - Mean_Annual_Precipitation  1 931.48
## - Harvest_Year               1 931.55
## - Mean_Annual_Temperature    1 931.56
## - Catchment_Size             1 931.94
## - Forest_Age                 1 932.53
## <none>                         933.48
## - Forest_Composition         2 942.27
## - Time_after_harvest         1 943.66
## - Forest_Harvest             4 944.80
## - Altitude                   1 945.11
## 
## Step:  AIC=931.48
## yi ~ Forest_Harvest + Forest_Composition + Time_after_harvest + 
##     Catchment_Size + Forest_Age + Mean_Annual_Temperature + Altitude + 
##     Harvest_Year
## 
##                           Df    AIC
## - Harvest_Year             1 929.57
## - Mean_Annual_Temperature  1 929.57
## - Catchment_Size           1 929.95
## - Forest_Age               1 930.72
## <none>                       931.48
## - Forest_Composition       2 940.98
## - Time_after_harvest       1 941.66
## - Forest_Harvest           4 944.23
## - Altitude                 1 944.24
## 
## Step:  AIC=929.57
## yi ~ Forest_Harvest + Forest_Composition + Time_after_harvest + 
##     Catchment_Size + Forest_Age + Mean_Annual_Temperature + Altitude
## 
##                           Df    AIC
## - Mean_Annual_Temperature  1 927.67
## - Catchment_Size           1 928.00
## - Forest_Age               1 928.92
## <none>                       929.57
## - Time_after_harvest       1 939.66
## - Forest_Composition       2 940.16
## - Altitude                 1 942.91
## - Forest_Harvest           4 943.09
## 
## Step:  AIC=927.67
## yi ~ Forest_Harvest + Forest_Composition + Time_after_harvest + 
##     Catchment_Size + Forest_Age + Altitude
## 
##                      Df    AIC
## - Catchment_Size      1 926.11
## - Forest_Age          1 927.05
## <none>                  927.67
## - Time_after_harvest  1 937.76
## - Forest_Composition  2 939.48
## - Altitude            1 940.92
## - Forest_Harvest      4 941.49
## 
## Step:  AIC=926.11
## yi ~ Forest_Harvest + Forest_Composition + Time_after_harvest + 
##     Forest_Age + Altitude
## 
##                      Df    AIC
## - Forest_Age          1 925.47
## <none>                  926.11
## - Time_after_harvest  1 935.98
## - Forest_Composition  2 937.74
## - Altitude            1 938.94
## - Forest_Harvest      4 939.64
## 
## Step:  AIC=925.47
## yi ~ Forest_Harvest + Forest_Composition + Time_after_harvest + 
##     Altitude
## 
##                      Df    AIC
## <none>                  925.47
## - Forest_Composition  2 935.97
## - Time_after_harvest  1 937.20
## - Altitude            1 937.62
## - Forest_Harvest      4 937.72
## Linear mixed-effects model fit by maximum likelihood
##   Data: es 
##   Log-likelihood: -449.7329
##   Fixed: yi ~ Forest_Harvest + Forest_Composition + Time_after_harvest +      Altitude 
##                  (Intercept)  Forest_Harvestpatchcut-high 
##                  0.516107070                 -0.192602991 
##   Forest_Harvestpatchcut-low Forest_Harvestselective-high 
##                  0.232387374                 -1.200503900 
##  Forest_Harvestselective-low        Forest_CompositionMix 
##                 -1.679633414                 -0.777111243 
##        Forest_CompositionDec           Time_after_harvest 
##                  0.721912517                 -0.106404194 
##                     Altitude 
##                  0.001878778 
## 
## Random effects:
##  Formula: ~1 + Time_after_harvest | Site_Number
##  Structure: General positive-definite, Log-Cholesky parametrization
##                    StdDev     Corr  
## (Intercept)        0.64950485 (Intr)
## Time_after_harvest 0.09474031 -0.071
## Residual           1.00000000       
## 
## Correlation Structure: Continuous AR(1)
##  Formula: ~Time_after_harvest | Site_Number 
##  Parameter estimate(s):
##       Phi 
## 0.4251468 
## Variance function:
##  Structure: fixed weights
##  Formula: ~(vi * LoEsc) 
## Number of Observations: 348
## Number of Groups: 52

Model selection based on AIC forward or backward selection will result in the same model than Wald F-tests

Additive model: choice of regression spline K

K sets the uppers limit on the degrees of freedom associated with a smooth (s()). K was determined based on help(choose.k). We have set bs=“ts” to use the thin plate regression splines.

#1 Decision based on residual patterns
fgam4 <- gamm(yi ~ Forest_Harvest + s(Time_after_harvest, bs="ts", k=4) + Forest_Composition + Altitude,
              random=list(Site_Number=~Time_after_harvest),
              weights=varFixed(~vi*LoEsc),
              control=list(sigma=1),
              correlation=corCAR1(form=~Time_after_harvest|Site_Number), method="ML", data=es)
plot(fgam4$gam,pages=1,residuals=T) #points are the residuals to whom the line is fitted. Less residuals increase uncertainty

gam.check(fgam4$gam) #not ideal (fourth plot with trend)

gam(residuals(fgam4$gam)~s(Time_after_harvest,bs="ts",k=4),data=es)
## 
## Family: gaussian 
## Link function: identity 
## 
## Formula:
## residuals(fgam4$gam) ~ s(Time_after_harvest, bs = "ts", k = 4)
## 
## Estimated degrees of freedom:
## 2.59  total = 3.59 
## 
## GCV score: 7.110808
FinalModel <- gamm(yi ~ Forest_Harvest + s(Time_after_harvest, bs="ts", k=20) + Forest_Composition + Altitude,
              random=list(Site_Number=~Time_after_harvest),
              weights=varFixed(~(vi*LoEsc)),
              control=list(sigma=1),
              correlation=corCAR1(form=~Time_after_harvest|Site_Number), method="ML", data=es)
plot(FinalModel$gam,pages=1,residuals=T) 
abline(h=0,lty=2)

gam.check(FinalModel$gam) 

gam(residuals(FinalModel$gam)~s(Time_after_harvest,bs="ts",k=20),data=es)
## 
## Family: gaussian 
## Link function: identity 
## 
## Formula:
## residuals(FinalModel$gam) ~ s(Time_after_harvest, bs = "ts", 
##     k = 20)
## 
## Estimated degrees of freedom:
## 6.33  total = 7.33 
## 
## GCV score: 6.053701

K= 20 is large enough.

Level-of-evidence weighting

What is the influence of the adjusted weighting, that multiplied level of evidence with variance?

Model_Without_LoE <-  gamm(yi ~ Forest_Harvest + s(Time_after_harvest, bs="ts", k=20) + Forest_Composition + Altitude,
              random=list(Site_Number=~Time_after_harvest),
              weights=varFixed(~(vi)),
              control=list(sigma=1),
              correlation=corCAR1(form=~Time_after_harvest|Site_Number), method="ML", data=es)
anova(Model_Without_LoE$gam)
## 
## Family: gaussian 
## Link function: identity 
## 
## Formula:
## yi ~ Forest_Harvest + s(Time_after_harvest, bs = "ts", k = 20) + 
##     Forest_Composition + Altitude
## 
## Parametric Terms:
##                    df      F  p-value
## Forest_Harvest      4  6.375 5.99e-05
## Forest_Composition  2  8.317    3e-04
## Altitude            1 19.004 1.75e-05
## 
## Approximate significance of smooth terms:
##                         edf Ref.df    F p-value
## s(Time_after_harvest) 15.31  19.00 18.9  <2e-16
AIC(FinalModel$lme,Model_Without_LoE$lme)
##                       df       AIC
## FinalModel$lme        13  888.8914
## Model_Without_LoE$lme 13 1443.3830
cor.test(es$vi,es$LoEsc)
## 
##  Pearson's product-moment correlation
## 
## data:  es$vi and es$LoEsc
## t = 3.1155, df = 346, p-value = 0.00199
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.06111864 0.26570490
## sample estimates:
##       cor 
## 0.1651882

Model selection as well as model interpretation is the same in model with and without level-of-evidence weighting.

Funnel plot

plot(sqrt(es$vi)~residuals(FinalModel$lme,type="normalized"),ylim=c(1,-1.8),pch=16,ylab="Standard error",xlab="Normalized residuals") 
rect(par("usr")[1], par("usr")[3], par("usr")[2], par("usr")[4], col ="grey")
lines((seq(1,-3,length.out=50)+1.96),seq(1,-3,length.out=50))
lines((-seq(1,-3,length.out=50)-1.96),seq(1,-3,length.out=50))
polygon(c(rev(-seq(1,-3,length.out=50)-1.96), seq(1,-3,length.out=50)+1.96), c(rev(seq(1,-3,length.out=50)), seq(1,-3,length.out=50)), col = "white", border = NA)
points(sqrt(es$vi)~residuals(FinalModel$lme,type="normalized"),pch=16,cex=0.5) #model without evidence weighting looks very similar.
abline(v=0)

Funnel plot for the additive mixed effects model. The normalized residuals are symmetrically distributed in a funnel plot and suggests no publication bias.

Egger’s regressions test

b1 <- sqrt(es$vi)*sqrt(1/(es$vi*LoEsc))
summary(lm(residuals(FinalModel$lme,type="normalized")*sqrt(1/(es$vi*LoEsc))~b1))
## 
## Call:
## lm(formula = residuals(FinalModel$lme, type = "normalized") * 
##     sqrt(1/(es$vi * LoEsc)) ~ b1)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -11.504  -1.024   0.044   1.045   9.713 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)
## (Intercept)   0.3690     2.0279   0.182    0.856
## b1           -0.6207     3.7264  -0.167    0.868
## 
## Residual standard error: 2.29 on 346 degrees of freedom
## Multiple R-squared:  8.018e-05,  Adjusted R-squared:  -0.00281 
## F-statistic: 0.02774 on 1 and 346 DF,  p-value: 0.8678

Intercept is not significant. There is no evidence for a publication bias.

Final Model

FinalModel <- gamm(yi ~ Forest_Harvest + s(Time_after_harvest, bs="tp", k=20) +Forest_Composition+Altitude,
                random=list(Site_Number=~Time_after_harvest),
                weights=varFixed(~(vi*LoEsc)),control=list(sigma=1),correlation=corCAR1(form=~Time_after_harvest|Site_Number),
                method="ML",data=es)
anova(FinalModel$gam)
## 
## Family: gaussian 
## Link function: identity 
## 
## Formula:
## yi ~ Forest_Harvest + s(Time_after_harvest, bs = "tp", k = 20) + 
##     Forest_Composition + Altitude
## 
## Parametric Terms:
##                    df      F  p-value
## Forest_Harvest      4  7.070 1.80e-05
## Forest_Composition  2  8.823 0.000185
## Altitude            1 25.325 7.99e-07
## 
## Approximate significance of smooth terms:
##                         edf Ref.df     F p-value
## s(Time_after_harvest) 11.46  11.46 11.07  <2e-16
AIC(FinalModel$lme)
## [1] 884.4257

Diagnostic plots

grid.arrange(plot(FinalModel$lme,type=c("p","smooth")),
             plot(FinalModel$lme,sqrt(abs(resid(.)))~fitted(.),
                  type=c("p","smooth"),ylab=expression(sqrt(abs(resid)))),
             plot(FinalModel$lme,resid(.,type="pearson")~Time_after_harvest,
                  type=c("p","smooth")),
             qqnorm(FinalModel$lme))

Figure 2 - Subgroup Analysis

Between-Site Variability

Calculating explained and unexplained between-site variability, total variability and within-site variability.

Figure 3: Between-Site Variability

The total between-site variability per year after intervention increased over the years more than the unexplained between-site variability. The upper line represents total variability. The lower line is the between-site variability explained by the model. b) Unexplained between-site variability to total unexplained variability (\(T^2_{\textrm{unexplained}} + S^2\)).