Arguments
- ...
Two or more named arguments; each name is a source label and each value is a bare admitted observation law or an
isdm_source()declaration. At least one source must be a count stream: the detection arm's offset is admitted only alongside a count arm sharing the same intensity, so an all-detection declaration is refused here rather than failing later.
Value
A mixed-family list understood by gllvmTMB(), with
family_var = "isdm_source". (The isdm_source_laws attribute is
informational only: internal validation rebuilds the declaration from the
list's names and laws, which survive reordering; the attribute does not.)
Details
Builds the family argument for an integrated species-distribution fit in
which any number of named observation sources – an opportunistic portal
stream, digitised literature records, checklists, a structured survey –
share one ecological linear predictor while each source keeps its own
observation law.
Each argument is named for a source and gives either a bare observation law
or isdm_source() with its source-specific observation formula. Two laws
are admitted, because both express the observation as a thinning of one
shared intensity: poisson() (a count stream; the offset is log effort) and
binomial("cloglog") (detection/non-detection; the offset is log support,
and the complementary log-log link is what makes a detection consistent with
the same intensity that generates the counts). Other links and families are
refused: a logit detection model, for instance, does not share a scale with
a count arm merely because both converge.
The data must carry an isdm_source column whose values are exactly the
declared source names, and – when the declaration mixes the two laws –
every trait must be observed by every declared source. Everything such a
fit reports is relative intensity: presence-only data cannot identify
absolute abundance, occupancy, or detectability, and none are estimated.
This interface is experimental and may change.
Examples
fam <- isdm_sources(
gbif = isdm_source(poisson(), observation = ~ access + popdens),
survey = isdm_source(poisson(), observation = ~ observer + method)
)
names(fam)
#> [1] "gbif" "survey"
## `dat` is long, one row per (cell, species, source), with an isdm_source
## column naming each row's source and log_support its known effort/area.
## Each source's observation covariates only enter that source's rows.
set.seed(1)
dat <- expand.grid(
cell_id = factor(paste0("c", 1:60)),
trait = factor(c("sp1", "sp2")),
isdm_source = factor(c("gbif", "survey"))
)
env <- rnorm(60) # one value per cell
u <- rnorm(60) # unmeasured cell effect shared by both species
dat$env <- env[as.integer(dat$cell_id)]
is_gbif <- dat$isdm_source == "gbif"
dat$log_support <- ifelse(is_gbif, log(2), 0)
dat$access <- ifelse(is_gbif, rnorm(nrow(dat)), NA)
dat$popdens <- ifelse(is_gbif, rnorm(nrow(dat)), NA)
dat$observer <- factor(ifelse(is_gbif, NA, sample(c("o1", "o2"), nrow(dat), TRUE)))
dat$method <- factor(ifelse(is_gbif, NA, sample(c("walk", "point"), nrow(dat), TRUE)))
eta <- c(0.2, -0.1)[dat$trait] + c(0.5, -0.4)[dat$trait] * dat$env +
c(0.6, 0.4)[dat$trait] * u[as.integer(dat$cell_id)] +
dat$log_support +
ifelse(is_gbif, -0.3 + 0.4 * dat$access + 0.2 * dat$popdens,
0.3 * (dat$observer == "o2") - 0.2 * (dat$method == "point"))
dat$value <- rpois(nrow(dat), exp(eta))
fit <- gllvmTMB(
value ~ 0 + trait + trait:env +
offset(log_support) + latent(0 + trait | cell_id, d = 1, unique = FALSE),
data = dat, trait = "trait", unit = "cell_id", family = fam
)
#> ℹ Dropped aliased source-observation column: "isdm_source:survey:(Intercept)".
#> ℹ The retained columns are source-specific effects relative to the ecological
#> `0 + trait` intercepts.
fit
#> Stacked-trait gllvmTMB fit
#> Traits = 2, cell_id = 60
#> Covstructs: latent_unit
#> Fixed effects (b_fix): 9
#> ML log L = -393.129 convergence = 0 engine = Laplace
#> Run gllvmTMB_diagnose(fit) for a full health check, or summary(fit) for parameter estimates.
