0

I would like to conduct a Bayesian meta-analysis on some plant population growth rates that I have already calculated. The structure of the data is nested because I have several plant species within multiple sites. For example, I have data on Species_1 and Species_2 in Site_1, Species_1 and Species_3 in Site_2, Species_3 and Species_4 in Site_3 and so on. I calculated the growth rates of each species population (i.e. Species_1 in Site_1, etc.) using a Bayesian hierarchical model using JAGS because I was interested in including the observation error during the sampling process. Thus, for each population I have a posterior distribution of the average growth rate.

Now, I would like to summarize the results into an overall growth rate and I was thinking about doing a Bayesian meta-analysis following the example of this paper:

Haase, P. et al. The recovery of European freshwater biodiversity has come to a halt. Nature 620, 582–588 (2023).

I was able to easily replicate their analysis using the R package brms, which uses Stan, but I would like to to it in JAGS to be consistent with the previous analysis. I have used the following model in brms:

set.seed(5345)
data_brms <- list(Site = paste("Site", sample(1:5, replace = T, size = 100), sep = '_'),
     Species = paste("Species", sample(1:10, replace = T, size = 100), sep = '_'),
     growth_rate_mean = rnorm(100, mean = 0, sd = 1),
     growth_rate_sd = rgamma(100, shape = 2, scale = 1/2)) 

brms_prior = c(set_prior("normal(0, 3)", class = "Intercept"),
           set_prior("gamma(0.001, 0.001)", class = "sd"))

mod_brms <- brm(growth_rate_mean|se(growth_rate_sd)  ~ 1 + (1|Site/Species), 
                data = dummy_data,
                prior = brms_prior,
                cores = 4,
                chains = 4,
                iter = 10000,
                warmup = 1000)

Which results in the following model:

functions {
}
data {
  int<lower=1> N;  // total number of observations
  vector[N] Y;  // response variable
  vector<lower=0>[N] se;  // known sampling error
  // data for group-level effects of ID 1
  int<lower=1> N_1;  // number of grouping levels
  int<lower=1> M_1;  // number of coefficients per level
  int<lower=1> J_1[N];  // grouping indicator per observation
  // group-level predictor values
  vector[N] Z_1_1;
  // data for group-level effects of ID 2
  int<lower=1> N_2;  // number of grouping levels
  int<lower=1> M_2;  // number of coefficients per level
  int<lower=1> J_2[N];  // grouping indicator per observation
  // group-level predictor values
  vector[N] Z_2_1;
  int prior_only;  // should the likelihood be ignored?
}
transformed data {
  vector<lower=0>[N] se2 = square(se);
}
parameters {
  real Intercept;  // temporary intercept for centered predictors
  vector<lower=0>[M_1] sd_1;  // group-level standard deviations
  vector[N_1] z_1[M_1];  // standardized group-level effects
  vector<lower=0>[M_2] sd_2;  // group-level standard deviations
  vector[N_2] z_2[M_2];  // standardized group-level effects
}
transformed parameters {
  real sigma = 0;  // dispersion parameter
  vector[N_1] r_1_1;  // actual group-level effects
  vector[N_2] r_2_1;  // actual group-level effects
  real lprior = 0;  // prior contributions to the log posterior
  r_1_1 = (sd_1[1] * (z_1[1]));
  r_2_1 = (sd_2[1] * (z_2[1]));
  lprior += normal_lpdf(Intercept | 0, 3);
  lprior += cauchy_lpdf(sd_1 | 0, 1)
    - 1 * cauchy_lccdf(0 | 0, 1);
  lprior += cauchy_lpdf(sd_2 | 0, 1)
    - 1 * cauchy_lccdf(0 | 0, 1);
}
model {
  // likelihood including constants
  if (!prior_only) {
    // initialize linear predictor term
    vector[N] mu = rep_vector(0.0, N);
    mu += Intercept;
    for (n in 1:N) {
      // add more terms to the linear predictor
      mu[n] += r_1_1[J_1[n]] * Z_1_1[n] + r_2_1[J_2[n]] * Z_2_1[n];
    }
    target += normal_lpdf(Y | mu, se);
  }
  // priors including constants
  target += lprior;
  target += std_normal_lpdf(z_1[1]);
  target += std_normal_lpdf(z_2[1]);
}
generated quantities {
  // actual population-level intercept
  real b_Intercept = Intercept;
}

I would like to replicate this model in JAGS, but I cannot get the nested random effects right. I tried followin this answer: Nested Random effect in JAGS/ WinBUGS but it did not work so I followed the second answer from this post: Three-level nested mixed-effects model but the results differ a lot from the ones I get from brms. My JAGS model is:

set.seed(5345)
data_jags <- list(N = 100,
                   Site = as.factor(paste("Site", sample(1:5, replace = T, size = 100), sep = '_')),
     Species = as.factor(paste("Species", sample(1:10, replace = T, size = 100), sep = '_')),
     growth_rate_mean = rnorm(100, mean = 0, sd = 1),
     growth_rate_sd = rgamma(100, shape = 2, scale = 1/2),
     nSites = 5,
     nSpecies = 10) 

# Set the interaction term:
interaction <- cbind(data_jags$Species, data_jags$Site)
interaction <- interaction[!duplicated(interaction),]
data_jags[[8]] <- as.factor(interaction[,2])
names(data_jags)[8] <- 'interaction'

# Define model:
sink("JAGSmodel.txt")
cat("
model{
  
  for(i in 1:N){
    
    P[i] <- 1/(growth_rate_sd[i]^2)
    growth_rate_mean[i] ~ dnorm(regression_fitted[i], P[i])
    regression_fitted[i] <- intercept + Species_randomeffect[Species[i]] + Site_randomeffect[Site[i]] 
  }
  
  # priors:
  regression_precision ~ dgamma(0.001, 0.001)

  intercept ~ dnorm(0, 1/9)

  # random effects
  for(i in 1:nSites){Site_randomeffect[i] ~ dnorm(0, Site_precision)}

  for(i in 1:nSpecies){Species_randomeffect[i] ~ dnorm(Site_randomeffect[interaction[i]], Species_precision)}

  Species_precision ~ dgamma(0.001, 0.001)
  Site_precision ~ dgamma(0.001, 0.001)
}
}
",fill = TRUE)
sink()

parameters <- c('intercept', 'Site_sd', 'Species_sd')
mod_jags <- run.jags(model = 'JAGSmodel.txt',
                     data = dummy_data,
                     n.chains = 4,
                     burnin = 1000,
                     sample = 10000,
                     thin = 1, 
                     parameters)

The results from each model are very different and I do not know if this is because brms is having trouble converging (it gives a warning with the dummy data) or because the JAGS model is incorrectly defined. If I use my original data brms works perfectly but the results from JAGS do not resemble the results from brms.

0 Answers0