EcoDiet is a new tool for assimilating data in food-web studies. The goal of the package is to quantify trophic interactions between food-web components by combining stomach content analyses and biotracers in a Bayesian hierarchical model. To do so, the model simultaneously estimates a probabilistic topology matrix of the trophic network and the diet matrix. The topology matrix is a probabilistic description of “who eats whom” in the food web nad is composed of the probabilities that trophic links exist between food-web components, i.e. the probabilities \(\eta\) that any prey is eaten by a given predator. The diet matrix is estimated conditionally to this topology and contains all diet proportions \(\Pi\), hence it expresses the contribution (in %) of any prey to a given predator’s diet.
The full EcoDiet model and its application to real and simulated
datasets are described in Hernvann et al. 2022, Ecol Appl. Use
citation("EcoDiet")
to get the full reference.
Several options are available within the present package:
Default option - only stomach content and biotracer data are integrated into EcoDiet.
Literature option - stomach content and biotracer data are integrated and results from expert knowledge or the literature are used to formulate informative priors on the topology and diet matrices.
The example showcased here is an artificial dataset, created to be simple to visualize and understand. In this example as in Hernvann et al. 2022, Ecol Appl the biotracers used are stable isotopes but EcoDiet could be used to treat other analyses (e.g., fatty acids, specific-compounds stable isotopes).
Before running the following code, please ensure that EcoDiet and the required tools are correctly installed and set up on your computer. Instructions can be found in the README’s instructions. If you’re all set, let’s load the EcoDiet package:
library(EcoDiet)
To apply EcoDiet to your own data, your stomach content, biotracer
and literature data should be in a specific format, similar to those of
following example. This data can for instance be imported into R using
.csv
files:
<- read.csv("./data/my_stomach_data.csv")
example_stomach_data <- read.csv("./data/my_biotracer_data.csv") example_biotracer_data
Here we will demonstrate how EcoDiet works on a simulated dataset stored within the EcoDiet package.
The stomach content table gathers the sum of occurrences of each prey trophic group in the analyzed stomachs of each consumer trophic group. The first column of the table contains the names of the prey trophic groups and the headers of the following columns contain the names of all the predator trophic groups. The last row of the table should be named “full”, and indicates how many (non-empty) stomachs have been analyzed for each trophic group.
<- read.csv(system.file("extdata", "example_stomach_data.csv",
example_stomach_data package = "EcoDiet"))
::kable(example_stomach_data) knitr
X | huge | large | medium | small |
---|---|---|---|---|
huge | 0 | 0 | 0 | 0 |
large | 11 | 0 | 0 | 0 |
medium | 9 | 22 | 0 | 0 |
small | 0 | 3 | 16 | 0 |
full | 19 | 24 | 17 | 0 |
In this example, for the “huge” animals, 19 stomachs were analyzed and contained remainings. Among these stomachs, 11 contained “large” animal remainings and 9 contained “medium” animal remainings.
If some trophic groups of the studied food web don’t have associated stomach content analyses, you should add a line in this table indicating the name of this group and 0 in the other rows (it is the case here for “small” animals that are at the base of the trophic network).
The Biotracer table contains the analyses of different tracer concentrations. Each line of the table represents one individual on which were conducted biotracer analyses for various elements (here, stable isotope analyses for carbon and nitrogen). The first column of the table should be called “group” and contain name of the trophic group the individual belongs. The rest of the table contains the measures, one column corresponding to one biotracer.
<- read.csv(system.file("extdata", "example_biotracer_data.csv",
example_biotracer_data package = "EcoDiet"))
::kable(example_biotracer_data) knitr
group | d13C | d15N |
---|---|---|
medium | -15.64284 | 13.840550 |
medium | -15.56745 | 12.600720 |
medium | -16.44420 | 14.037290 |
medium | -17.16711 | 13.133810 |
small | -17.95860 | 10.443507 |
small | -16.56196 | 10.789742 |
small | -17.04855 | 11.236032 |
small | -17.14060 | 8.976896 |
small | -16.23605 | 8.580734 |
large | -15.24835 | 16.433410 |
large | -14.03405 | 16.299340 |
large | -16.76164 | 17.009600 |
large | -16.53439 | 15.878830 |
large | -14.93301 | 16.633490 |
huge | NA | NA |
All the trophic groups of the studied food web should be present in this biotracer table. Thus, if biotracer analyses are missing for one given trophic group you still have to enter one line indicating the name of the trophic group and NA in the following columnds (as it is the case for the “huge” group).
The biotracers like stable isotope analyses are integrated in the model based on the trophic enrichment concept. Thus, for each biotracer informed, you also need to define the corresponding trophic discrimination factors corresponding to your the biotracers. In this example, we use common trophic discrimination factors for carbon and nitrogen:
= c(0.8, 3.4) trophic_discrimination_factor
If you have data extracted from the literature, skip this and go to section 3.
Read this section if you don’t want to integrate
information from the literature / expert knowledge. This is specified
using the literature_configuration
argument.
<- FALSE literature_configuration
The preprocess_data
function checks and rearranges the
input data into a specific format that is read when running the EcoDiet
model:
<- preprocess_data(stomach_data = example_stomach_data,
data biotracer_data = example_biotracer_data,
trophic_discrimination_factor = c(0.8, 3.4),
literature_configuration = literature_configuration
)#> The model will investigate the following trophic links:
#> huge large medium small
#> huge 0 0 0 0
#> large 1 0 0 0
#> medium 1 1 0 0
#> small 0 1 1 0
Error messages will appear if the input data hasn’t been provided in the expected shape. Please read carefully the error message and rearrange your data in the correct format.
Stomach content dataset dominated by numerous small values of
occurrence might be problematical as to few groups could be identified
as potential prey. To avoid such situations, you can choose to upscale
the stomach content data so that occurrences are artificially increased
but their relative importance are conserved. This is performed by
specifying rescale_stomach = TRUE
when preprocessing the
data.
<- preprocess_data(biotracer_data = example_biotracer_data,
data trophic_discrimination_factor = c(0.8, 3.4),
literature_configuration = literature_configuration,
stomach_data = example_stomach_data,
rescale_stomach = TRUE)
#> The model will investigate the following trophic links:
#> huge large medium small
#> huge 0 0 0 0
#> large 1 0 0 0
#> medium 1 1 0 0
#> small 0 1 1 0
By default, the links that will be investigated by the model will be
those derived from at least one observation in the stomach content
analyses. This is a conservative assumption to avoid investigating all
the possible trophic links in the food web, since it would make the
model too complex and require too long runs, while also reduce the
discrimination power of the model (see Hernvann et al. 2022). The
trophic links that will be investigated can be summarized by a fixed
topology computed by the preprocess_data
based on stomach
contents (i.e., data$o
):
<- 1 * (data$o > 0)
topology print(topology)
#> huge large medium small
#> huge 0 0 0 0
#> large 1 0 0 0
#> medium 1 1 0 0
#> small 0 1 1 0
If you want to add other important link that may not be observed in scat contents (or, on the contrary, remove false positive trophic links identified in the stomach contents), you can modify directly this binary topology matrix. This operation can be useful, for instance, if your stomach sampling size is too low and you missed a prey you are definitely sure that the predator feeds on, or if you know that the identification of a prey will be reduced due to very small size or high digestibility. To specify that the “huge” animal can also eat “small” animals, you can do:
"small", "huge"] <- 1
topology[print(topology)
#> huge large medium small
#> huge 0 0 0 0
#> large 1 0 0 0
#> medium 1 1 0 0
#> small 1 1 1 0
To run EcoDiet on this updated binary topology, you will have to
append the previous one by re-running the preprocess_data
as follows:
<- preprocess_data(biotracer_data = example_biotracer_data,
data trophic_discrimination_factor = c(0.8, 3.4),
literature_configuration = literature_configuration,
topology = topology,
stomach_data = example_stomach_data)
#> The model will investigate the following trophic links:
#> huge large medium small
#> huge 0 0 0 0
#> large 1 0 0 0
#> medium 1 1 0 0
#> small 1 1 1 0
If you don’t have data extracted from the literature, skip this and go to section 4.
Read this section if you do want to integrate
information from the literature / expert knowledge. This is specified
using the literature_configuration
argument.
<- TRUE literature_configuration
A literature diet table is used to set priors on the trophic link probabilities \(\eta\) and the diet proportions \(\Pi\). This table is similar to the stomach contents table, as all trophic groups must be included in the columns and rows. The numbers are the average diet proportions found in the literature. Here, the selected studies have identified that “huge” animals eat equally “large” and “medium” animals (thus the 0.5 and 0.5 numbers in the first column). The proportions for a given predator (i.e., within a given column) must sum to 1. The “small” animals are at the base of the ecosystem, so the column is filled with zeros.
The last row of the table corresponds to the literature pedigree score. This score (a number from 0 to 1) quantifies the literature reliability on each predator’s diet. Here the dietary proportions from the literature are used to produce reliable estimates for the “huge” animals, e.g., the pedigree score associated is high (0.9). On the contrary, the diet proportions for the “medium” animals come from an older article focusing on a very different ecosystem so estimates produced are less reliable, e.g, the pedigree score is low (0.2). The pedigree score for the “small” animals is set at 1, because this group eats nothing. For more details please read the reference article.
<- system.file("extdata", "example_literature_diets.csv",
example_literature_diets_path package = "EcoDiet")
<- read.csv(example_literature_diets_path)
example_literature_diets ::kable(example_literature_diets) knitr
X | huge | large | medium | small |
---|---|---|---|---|
huge | 0.0 | 0.0 | 0.0 | 0 |
large | 0.5 | 0.0 | 0.0 | 0 |
medium | 0.5 | 0.7 | 0.0 | 0 |
small | 0.0 | 0.3 | 1.0 | 0 |
pedigree | 0.9 | 0.6 | 0.2 | 1 |
This summary of the literature data will be used to formulate:
The priors on the topology matrix’s \(\eta\)s. If a given literature diet proportion is zero, the corresponding prior Beta distribution of \(\eta\) will be shifted toward 0. If the proportion is positive, the distribution will be shifted toward 1.
The priors on the diet matrix’s \(\Pi\)s. The literature diet proportions are entered as the hyperparameters of the prior Dirichlet distribution of \(\Pi\).
The Pedigree scores are used to determine the priors’ precision. Other parameters can be used to adjust the prior distributions:
nb_literature
parameter. The higher the number, the
stronger the weight will be of the literature in the final inference on
\(\eta\). Setting this parameter to 10
is like saying that the prior from the literature will weigh as much as
the additional data from 10 stomachs. Thus for any particular
application, nb_literature
should be set to a value smaller
than the sample size in the available stomach content data.= 10 nb_literature
literature_slope
parameter (a value between 0 and
1). The higher the number, the stronger the weight will be of the
literature in the final inference on \(\Pi\). You should set this value depending
on the value of your data (number of biotracers, etc).= 0.5 literature_slope
The preprocess_data
function then checks and rearranges
the data in a specific format so that the EcoDiet model can be run:
<- preprocess_data(biotracer_data = example_biotracer_data,
data trophic_discrimination_factor = c(0.8, 3.4),
literature_configuration = literature_configuration,
stomach_data = example_stomach_data,
literature_diets = example_literature_diets,
nb_literature = 10,
literature_slope = 0.5)
#> The model will investigate the following trophic links:
#> huge large medium small
#> huge 0 0 0 0
#> large 1 0 0 0
#> medium 1 1 0 0
#> small 0 1 1 0
If any error appears, it means your data is not in the correct format. Please read the error message and try to rearrange the data in the correct format.
If you have a lot of small values in the stomach occurences, you can choose to upscale the stomach content data:
<- preprocess_data(biotracer_data = example_biotracer_data,
data trophic_discrimination_factor = c(0.8, 3.4),
literature_configuration = literature_configuration,
stomach_data = example_stomach_data,
rescale_stomach = TRUE,
literature_diets = example_literature_diets,
nb_literature = 10,
literature_slope = 0.5)
#> The model will investigate the following trophic links:
#> huge large medium small
#> huge 0 0 0 0
#> large 1 0 0 0
#> medium 1 1 0 0
#> small 0 1 1 0
These are the links that will be investigated by the model. It is not
wise to assume that all the trophic links are possible. You therefore
need to keep only the reasonnable trophic links (e.g., a shrimp cannot
eat a whale). The matrix displayed by the preprocess_data
function is based by default on the stomach content data
(data$o
) and on the literature diet matrix
(data$alpha_lit
):
<- 1 * ((data$o > 0) | (data$alpha_lit > 0))
topology print(topology)
#> huge large medium small
#> huge 0 0 0 0
#> large 1 0 0 0
#> medium 1 1 0 0
#> small 0 1 1 0
If you want to add another trophic link, you can modify directly the binary topology matrix. It can be useful if you are sure that a prey is consumed by a given predator. However the trophic link is not observed in the stomach content data, and the study extracted from the literature did not identify the prey. To specify that the “huge” animal can also eat “small” animals, you can do:
"small", "huge"] <- 1
topology[print(topology)
#> huge large medium small
#> huge 0 0 0 0
#> large 1 0 0 0
#> medium 1 1 0 0
#> small 1 1 1 0
The new topology matrix can now be entered as an argument of the
preprocess_data
function:
<- preprocess_data(biotracer_data = example_biotracer_data,
data trophic_discrimination_factor = c(0.8, 3.4),
literature_configuration = literature_configuration,
topology = topology,
stomach_data = example_stomach_data,
literature_diets = example_literature_diets,
nb_literature = 10,
literature_slope = 0.5)
#> The model will investigate the following trophic links:
#> huge large medium small
#> huge 0 0 0 0
#> large 1 0 0 0
#> medium 1 1 0 0
#> small 1 1 1 0
You can visualize your data with the plot_data
function:
plot_data(biotracer_data = example_biotracer_data,
stomach_data = example_stomach_data)
#> Warning: Use of `biotracer_data$group` is discouraged.
#> ℹ Use `group` instead.
You can save the figures as PNG in the current folder using:
plot_data(biotracer_data = example_biotracer_data,
stomach_data = example_stomach_data,
save = TRUE, save_path = ".")
Whether the priors are non-informative or informed by the literature, you can plot the mean of the prior distributions for the trophic link probabilities \(\eta\) and the diet proportions \(\Pi\):
plot_prior(data, literature_configuration)
You can also see the prior distributions for one trophic group (or predator):
plot_prior(data, literature_configuration, pred = "huge")
This way, you can change the prior parameters and see how it affects
the prior distributions. Here, we will change the
nb_literature
parameter from 10 to 2:
<- preprocess_data(biotracer_data = example_biotracer_data,
data trophic_discrimination_factor = c(0.8, 3.4),
literature_configuration = literature_configuration,
topology = topology,
stomach_data = example_stomach_data,
literature_diets = example_literature_diets,
nb_literature = 2,
literature_slope = 0.5)
#> The model will investigate the following trophic links:
#> huge large medium small
#> huge 0 0 0 0
#> large 1 0 0 0
#> medium 1 1 0 0
#> small 1 1 1 0
plot_prior(data, literature_configuration, pred = "huge", variable = "eta")
The write_model
function writes the model in the BUGS
syntax. Here You need to specify whether you want to use or not priors
form the literature since the model structure will be affected by this
choice. The model is written as a .txt for which you should
specify a path and name through the file.name
argument.
To see the written model, you can turn on visualization using
print.model=TRUE
or opening the saved .txt
file
<- "mymodel.txt"
filename write_model(file.name = filename, literature_configuration = literature_configuration, print.model = F)
First, run the model as a test (i.e., low adaption phase and low
number of iterations) to check that the model is compiling properly.
Specifying run_param="test"
will by default run the model
with nb_iter=1000 and nb_burnin=500.
<- run_model(filename, data, run_param = "test")
mcmc_output #>
#> Processing function input.......
#>
#> Done.
#>
#> Compiling model graph
#> Resolving undeclared variables
#> Allocating nodes
#> Graph information:
#> Observed stochastic nodes: 20
#> Unobserved stochastic nodes: 41
#> Total graph size: 393
#>
#> Initializing model
#>
#> Adaptive phase, 500 iterations x 3 chains
#> If no progress bar appears JAGS has decided not to adapt
#>
#>
#> Burn-in phase, 500 iterations x 3 chains
#>
#>
#> Sampling from joint posterior, 500 iterations x 3 chains
#>
#>
#> Calculating statistics.......
#> Warning in doTryCatch(return(expr), name, parentenv, handler): At least one Rhat
#> value could not be calculated.
#>
#> Done.
#>
#> /!\ Convergence warning:
#> Out of the 13 variables, 4 variables have a Gelman-Rubin statistic > 1.1.
#> You may consider modifying the model run settings.
#> The variables with the poorest convergence are: PI[4,1], PI[3,2], PI[4,2], PI[2,1].
#> JAGS output for model 'mymodel.txt', generated by jagsUI.
#> Estimates based on 3 chains of 1000 iterations,
#> adaptation = 500 iterations (sufficient),
#> burn-in = 500 iterations and thin rate = 1,
#> yielding 1500 total samples from the joint posterior.
#> MCMC ran for 0.021 minutes at time 2024-03-25 09:50:23.
#>
#> mean sd 2.5% 50% 97.5% overlap0 f Rhat n.eff
#> eta[2,1] 0.606 0.101 0.406 0.608 0.790 FALSE 1 1.004 382
#> eta[3,1] 0.519 0.104 0.320 0.514 0.721 FALSE 1 1.002 728
#> eta[4,1] 0.042 0.041 0.001 0.029 0.153 FALSE 1 1.000 1500
#> eta[3,2] 0.891 0.058 0.758 0.899 0.975 FALSE 1 1.000 1500
#> eta[4,2] 0.191 0.074 0.071 0.183 0.359 FALSE 1 1.008 243
#> eta[4,3] 0.897 0.068 0.734 0.911 0.985 FALSE 1 1.004 531
#> PI[2,1] 0.455 0.373 0.000 0.415 1.000 FALSE 1 1.121 21
#> PI[3,1] 0.363 0.371 0.000 0.222 1.000 FALSE 1 1.089 27
#> PI[4,1] 0.182 0.270 0.000 0.019 0.882 FALSE 1 1.267 13
#> PI[3,2] 0.925 0.168 0.357 1.000 1.000 FALSE 1 1.218 20
#> PI[4,2] 0.075 0.168 0.000 0.000 0.643 FALSE 1 1.218 20
#> PI[4,3] 1.000 0.000 1.000 1.000 1.000 FALSE 1 NA 1
#> deviance 76.051 6.135 65.724 75.509 90.504 FALSE 1 1.002 949
#>
#> **WARNING** Rhat values indicate convergence failure.
#> Rhat is the potential scale reduction factor (at convergence, Rhat=1).
#> For each parameter, n.eff is a crude measure of effective sample size.
#>
#> overlap0 checks if 0 falls in the parameter's 95% credible interval.
#> f is the proportion of the posterior with the same sign as the mean;
#> i.e., our confidence that the parameter is positive or negative.
#>
#> DIC info: (pD = var(deviance)/2)
#> pD = 18.8 and DIC = 94.854
#> DIC is an estimate of expected predictive error (lower is better).
The low numbers won’t be enough to achieve a satisfactory model
convergence. You should progressively increase the number of adaptation
steps nb_adapt
and of iterations nb_iter
while
checking the “Convergence warnings” message. You can specify these model
run parameters by specifying
run_param=list(nb_iter=iter, nb_burnin=burnin, nb_thin=thin)
.
There are also a couple of default run parameters (“very
short”,“short”,“normal”,“long”,“very
long”) that you can use in the with run_param
and
learn about by calling ?run_param
Be aware that, depending on your data and especially the number of trophic groups and investigate trophic interactions, the model can take hours or days to run.
<- run_model(filename, data, run_param=list(nb_iter=10000, nb_burnin=5000, nb_thin=5))
mcmc_output <- run_model(filename, data, run_param=list(nb_iter=50000, nb_burnin=25000, nb_thin=25))
mcmc_output <- run_model(filename, data, run_param=list(nb_iter=100000, nb_burnin=50000, nb_thin=50))
mcmc_output
<- run_model(filename, data, run_param=list(nb_iter=50000, nb_burnin=25000, nb_thin=25)) mcmc_output_example
Note that for much complex case studies, the dimension of the model may be considerable hence the time required by the runs may be dramatically long. In that context, while analyzing your results carefully, you might be willing to use your model outputs if a only a very limited number of variables don’t reach convergence after especially long runs.
Once a model reaches convergence objectives, don’t forget to save it on your machine.
save(mcmc_output_example, file = "./data/mcmc_output_example.rda")
Here we provide the diagnose_model
function to perform
simple diagnoses on the EcoDiet run. It displays the number of variables
for which the Gelman-Rubin test remains higher than different
thresholds, highlighting also the 10 worst variables in terms of
convergence. The object created contains these values for all the model
variables.
<- diagnose_model(mcmc_output_example)
Gelman_model #>
#> ################################################################################
#> # Gelman-Rubin Diagnostic
#> ################################################################################
#> In EcoDiet, we recommend a that Gelman diagnostic is < 1.1
#> Out of 11 variables:
#> 0 > 1.01
#> 0 > 1.05
#> 0 > 1.1
#> The worst variables are:
#> Point est. Upper C.I.
#> PI[2,1] 1.006849 1.025859
#> PI[3,1] 1.006849 1.025859
#> PI[3,2] 1.004532 1.009351
#> PI[4,2] 1.004532 1.009351
#> eta[3,1] 1.001312 1.004666
#> eta[4,3] 1.001031 1.002551
#> eta[4,2] 1.000933 1.004568
#> eta[2,1] 1.000618 1.001747
#> eta[3,2] 1.000299 1.002006
#> deviance 1.000124 1.001733
print(Gelman_model)
#> $gelman
#> Point est. Upper C.I.
#> eta[2,1] 1.000618 1.001747
#> eta[3,1] 1.001312 1.004666
#> eta[3,2] 1.000299 1.002006
#> eta[4,2] 1.000933 1.004568
#> eta[4,3] 1.001031 1.002551
#> PI[2,1] 1.006849 1.025859
#> PI[3,1] 1.006849 1.025859
#> PI[3,2] 1.004532 1.009351
#> PI[4,2] 1.004532 1.009351
#> deviance 1.000124 1.001733
The function can also be used to produce diagnostic plots and save them as a .pdf file. Complex models will have so many variables that the process can be very long so the user can also specify the variable for which graphs should be produced and stored.
diagnose_model(mcmc_output_example, var.to.diag = "all", save = TRUE)
The object output by the run_model
function contains all
MCMC samples, summary statistics and the configuration of the run:
str(mcmc_output_example)
#> List of 24
#> $ sims.list :List of 3
#> ..$ eta : num [1:3000, 1:4, 1:3] NA NA NA NA NA NA NA NA NA NA ...
#> ..$ PI : num [1:3000, 1:4, 1:3] NA NA NA NA NA NA NA NA NA NA ...
#> ..$ deviance: num [1:3000] 73.8 89.2 75.8 80.1 82 ...
#> $ mean :List of 3
#> ..$ eta : num [1:4, 1:3] NA 0.699 0.63 NA NA ...
#> ..$ PI : num [1:4, 1:3] NA 0.51 0.49 NA NA ...
#> ..$ deviance: num 75.8
#> $ sd :List of 3
#> ..$ eta : num [1:4, 1:3] NA 0.0824 0.0875 NA NA ...
#> ..$ PI : num [1:4, 1:3] NA 0.378 0.378 NA NA ...
#> ..$ deviance: num 6.1
#> $ q2.5 :List of 3
#> ..$ eta : num [1:4, 1:3] NA 0.532 0.446 NA NA ...
#> ..$ PI : num [1:4, 1:3] NA 4.57e-11 1.09e-11 NA NA ...
#> ..$ deviance: num 65.7
#> $ q25 :List of 3
#> ..$ eta : num [1:4, 1:3] NA 0.644 0.572 NA NA ...
#> ..$ PI : num [1:4, 1:3] NA 0.1275 0.0806 NA NA ...
#> ..$ deviance: num 71.5
#> $ q50 :List of 3
#> ..$ eta : num [1:4, 1:3] NA 0.705 0.634 NA NA ...
#> ..$ PI : num [1:4, 1:3] NA 0.503 0.497 NA NA ...
#> ..$ deviance: num 75.2
#> $ q75 :List of 3
#> ..$ eta : num [1:4, 1:3] NA 0.758 0.69 NA NA ...
#> ..$ PI : num [1:4, 1:3] NA 0.919 0.873 NA NA ...
#> ..$ deviance: num 79.6
#> $ q97.5 :List of 3
#> ..$ eta : num [1:4, 1:3] NA 0.848 0.794 NA NA ...
#> ..$ PI : num [1:4, 1:3] NA 1 1 NA NA ...
#> ..$ deviance: num 89.2
#> $ overlap0 :List of 3
#> ..$ eta : logi [1:4, 1:3] NA FALSE FALSE NA NA NA ...
#> ..$ PI : logi [1:4, 1:3] NA FALSE FALSE NA NA NA ...
#> ..$ deviance: logi FALSE
#> $ f :List of 3
#> ..$ eta : num [1:4, 1:3] NA 1 1 NA NA NA 1 1 NA NA ...
#> ..$ PI : num [1:4, 1:3] NA 1 1 NA NA NA 1 1 NA NA ...
#> ..$ deviance: num 1
#> $ Rhat :List of 3
#> ..$ eta : num [1:4, 1:3] NA 1 1 NA NA ...
#> ..$ PI : num [1:4, 1:3] NA 1.01 1.01 NA NA ...
#> ..$ deviance: num 1
#> $ n.eff :List of 3
#> ..$ eta : num [1:4, 1:3] NA 3000 1606 NA NA ...
#> ..$ PI : num [1:4, 1:3] NA 281 281 NA NA ...
#> ..$ deviance: num 3000
#> $ pD : num 18.6
#> $ DIC : num 94.4
#> $ summary : num [1:11, 1:11] 0.699 0.63 0.907 0.31 0.906 ...
#> ..- attr(*, "dimnames")=List of 2
#> .. ..$ : chr [1:11] "eta[2,1]" "eta[3,1]" "eta[3,2]" "eta[4,2]" ...
#> .. ..$ : chr [1:11] "mean" "sd" "2.5%" "25%" ...
#> $ samples :List of 3
#> ..$ : 'mcmc' num [1:1000, 1:11] 0.591 0.639 0.775 0.722 0.676 ...
#> .. ..- attr(*, "dimnames")=List of 2
#> .. .. ..$ : NULL
#> .. .. ..$ : chr [1:11] "eta[2,1]" "eta[3,1]" "eta[3,2]" "eta[4,2]" ...
#> .. ..- attr(*, "mcpar")= num [1:3] 2e+05 3e+05 1e+02
#> ..$ : 'mcmc' num [1:1000, 1:11] 0.581 0.616 0.722 0.744 0.6 ...
#> .. ..- attr(*, "dimnames")=List of 2
#> .. .. ..$ : NULL
#> .. .. ..$ : chr [1:11] "eta[2,1]" "eta[3,1]" "eta[3,2]" "eta[4,2]" ...
#> .. ..- attr(*, "mcpar")= num [1:3] 2e+05 3e+05 1e+02
#> ..$ : 'mcmc' num [1:1000, 1:11] 0.623 0.804 0.627 0.701 0.721 ...
#> .. ..- attr(*, "dimnames")=List of 2
#> .. .. ..$ : NULL
#> .. .. ..$ : chr [1:11] "eta[2,1]" "eta[3,1]" "eta[3,2]" "eta[4,2]" ...
#> .. ..- attr(*, "mcpar")= num [1:3] 2e+05 3e+05 1e+02
#> ..- attr(*, "class")= chr "mcmc.list"
#> $ modfile : chr "mymodel.txt"
#> $ model :List of 3
#> ..$ cluster1:List of 8
#> .. ..$ ptr :function ()
#> .. ..$ data :function ()
#> .. ..$ model :function ()
#> .. ..$ state :function (internal = FALSE)
#> .. ..$ nchain :function ()
#> .. ..$ iter :function ()
#> .. ..$ sync :function ()
#> .. ..$ recompile:function ()
#> .. ..- attr(*, "class")= chr "jags"
#> ..$ cluster2:List of 8
#> .. ..$ ptr :function ()
#> .. ..$ data :function ()
#> .. ..$ model :function ()
#> .. ..$ state :function (internal = FALSE)
#> .. ..$ nchain :function ()
#> .. ..$ iter :function ()
#> .. ..$ sync :function ()
#> .. ..$ recompile:function ()
#> .. ..- attr(*, "class")= chr "jags"
#> ..$ cluster3:List of 8
#> .. ..$ ptr :function ()
#> .. ..$ data :function ()
#> .. ..$ model :function ()
#> .. ..$ state :function (internal = FALSE)
#> .. ..$ nchain :function ()
#> .. ..$ iter :function ()
#> .. ..$ sync :function ()
#> .. ..$ recompile:function ()
#> .. ..- attr(*, "class")= chr "jags"
#> $ parameters : chr [1:3] "eta" "PI" "deviance"
#> $ mcmc.info :List of 10
#> ..$ n.chains : num 3
#> ..$ n.adapt : num [1:3] 100 100 100
#> ..$ sufficient.adapt: logi [1:3] TRUE TRUE TRUE
#> ..$ n.iter : num 3e+05
#> ..$ n.burnin : num 2e+05
#> ..$ n.thin : num 100
#> ..$ n.samples : num 3000
#> ..$ end.values :List of 3
#> .. ..$ : Named num [1:11] 0.03392 0.96608 0.99163 0.00837 1 ...
#> .. .. ..- attr(*, "names")= chr [1:11] "PI[2,1]" "PI[3,1]" "PI[3,2]" "PI[4,2]" ...
#> .. ..$ : Named num [1:11] 1.00 3.19e-07 9.48e-01 5.22e-02 1.00 ...
#> .. .. ..- attr(*, "names")= chr [1:11] "PI[2,1]" "PI[3,1]" "PI[3,2]" "PI[4,2]" ...
#> .. ..$ : Named num [1:11] 0.000195 0.999805 0.998672 0.001328 1 ...
#> .. .. ..- attr(*, "names")= chr [1:11] "PI[2,1]" "PI[3,1]" "PI[3,2]" "PI[4,2]" ...
#> ..$ elapsed.mins : num 1.72
#> ..$ n.cores : num 3
#> $ run.date : POSIXct[1:1], format: "2022-12-28 14:02:18"
#> $ parallel : logi TRUE
#> $ bugs.format: logi FALSE
#> $ calc.DIC : logi TRUE
#> - attr(*, "class")= chr "jagsUI"
Please read the documentation of the jagsUI package for more information.
Below we provide some functions to for a simple exploration of the results.
The model’s outputs are the approximated a posteriori
distributions for the trophic links probabilities \(\eta\) and the diet proportions \(\Pi\). You can visualize the mean of these
distribitions with the plot_results
function:
plot_results(mcmc_output_example, data)
You can access the main statistics by variable directly from the
jagsUI
object returned by the rrun_model
function, including the mean value of the variables:
print(mcmc_output_example$summary[,"mean"])
#> eta[2,1] eta[3,1] eta[3,2] eta[4,2] eta[4,3] PI[2,1] PI[3,1]
#> 0.6989887 0.6298710 0.9065303 0.3095975 0.9057456 0.5103627 0.4896373
#> PI[3,2] PI[4,2] PI[4,3] deviance
#> 0.8851660 0.1148340 1.0000000 75.8304573
The probability distributions can be plotted for one predator:
plot_results(mcmc_output_example, data, pred = "huge")
#> Warning: The dot-dot notation (`..scaled..`) was deprecated in ggplot2 3.4.0.
#> ℹ Please use `after_stat(scaled)` instead.
#> ℹ The deprecated feature was likely used in the EcoDiet package.
#> Please report the issue at <https://github.com/pyhernvann/EcoDiet/issues>.
#> This warning is displayed once every 8 hours.
#> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
#> generated.
plot_results(mcmc_output_example, data, pred = "large")
You actually have the possibility to monitor and output the
statistics of all the model parameters. For example you may be
interested by the variable \(\delta\)
that represents the trophic discrimination factor. In the EcoDiet model,
a different trophic discrimination factor is used for each trophic group
and for each element, allowing some differences between species. We can
chose to monitor these parameters when running the model by using the
variables_to_save
argument:
<- run_model(filename, data,
mcmc_output_delta variables_to_save = c("delta"),
run_param = "test")
And now you can access the mean value using:
print(mcmc_output_delta$summary[,"mean"])