Reads a table of detections and reports which analyses it admits, and which it does not, with the reason. Nothing is fitted and nothing is estimated.
Arguments
- data
A data frame with one row per detection, as
sweep_models()takes:distancefor exact distances, ordistbeginanddistendfor binned ones.
Value
An object of class dsfit_structure: a list with table (one row
per question, with check, supported and detail) and summary (the
counts and distance type behind it). supported is TRUE, FALSE, or
NA where the structure is present but incomplete.
Why this exists
Most of what decides whether an analysis is possible is structural, and none of it is announced by the data. Whether distances are exact or binned decides which goodness-of-fit test can be computed. Whether a survey ran two independent observer teams decides whether perception bias is estimable at all — and that is a property of the survey programme, not of the archive its data ends up in, so a pooled extract may or may not carry it.
The failure this guards against is not an error but a silence: fitting a single-observer dataset and reporting the result as though perception had been handled. That produces a number, and the number is wrong by a factor. Asking here turns "you had to know that" into something the package says.
What it does not tell you
That an analysis is supported is a statement about structure, not about whether it is a good idea. Enough detections to fit a detection function is not enough detections to fit one well, and a covariate being present is not a reason to put it in a model.
Availability is reported as unsupported for every table, which is not a
defect in any particular dataset: it cannot be estimated from sighting
distances by construction, because an animal submerged for the whole pass is
missed at every distance equally and leaves no signature. It is computed from
dive data instead — see availability().
See also
prepare_distance_data(), which enforces what this only reports.
availability() and g0() for the components this cannot supply.
Examples
set.seed(1)
d <- data.frame(
object = 1:200,
distance = abs(rnorm(200, 0, 120)),
beaufort = sample(0:4, 200, replace = TRUE)
)
detection_structure(d)
#> <dsfit_structure>
#> 200 rows, 200 exact distances
#> nearest detection at 0.1326 - a blind spot beneath the platform would show here
#>
#> can:
#> fit a detection function 200 exact distances; at or above the 60-80 usually suggested
#> test fit with Cramer-von Mises exact distances have an empirical distribution to test
#> test fit with chi-square over cutpoints mrds chooses, which makes it the weaker test here
#> fit covariate models candidates: beaufort
#>
#> cannot:
#> estimate perception bias no double-observer structure: no `observer` or `detected` column. Perception needs two independent teams and cannot be recovered from a single-observer survey at any sample size
#> estimate availability not estimable from distances by construction: a submerged animal is missed at every distance equally. Compute it from dive data with availability()
#> carry group size to abundance no `size` column; abundance would count groups, not individuals
#>
#> Structure only. That something is supported is not a reason to do it.
# Binned distances admit a different goodness-of-fit test
b <- data.frame(object = 1:60, distbegin = rep(c(0, 100, 200), 20),
distend = rep(c(100, 200, 300), 20))
detection_structure(b)
#> <dsfit_structure>
#> 60 rows, 60 binned distances
#>
#> can:
#> fit a detection function 60 binned distances; at or above the 60-80 usually suggested
#> test fit with chi-square over the survey's own bins
#>
#> cannot:
#> test fit with Cramer-von Mises needs exact distances; binned fits have no empirical distribution
#> fit covariate models no columns beyond the structural ones vary
#> estimate perception bias no double-observer structure: no `observer` or `detected` column. Perception needs two independent teams and cannot be recovered from a single-observer survey at any sample size
#> estimate availability not estimable from distances by construction: a submerged animal is missed at every distance equally. Compute it from dive data with availability()
#> carry group size to abundance no `size` column; abundance would count groups, not individuals
#>
#> Structure only. That something is supported is not a reason to do it.