
GLMM-based aerial effort estimation with diurnal correction
Source:R/creel-estimates-aerial-glmm.R
estimate_effort_aerial_glmm.RdEstimates total angler effort from aerial creel surveys using a generalized linear mixed model (GLMM), following the approach of Askey et al. (2018). When flights occur at non-random times of day, simple scaling of instantaneous counts can over- or under-estimate daily effort. This function fits a negative-binomial GLMM (or user-specified family) to model how angler counts change through the day, then integrates the fitted diurnal curve over the fishing day to obtain a bias-corrected effort estimate.
The default model is the quadratic temporal model from Askey (2018):
count ~ poly(time_col, 2) + (1 | date), fitted via
lme4::glmer.nb(). Variance is propagated via the delta method (default) or
parametric bootstrap (lme4::bootMer()).
Usage
estimate_effort_aerial_glmm(
design,
time_col,
formula = NULL,
family = NULL,
boot = FALSE,
nboot = 500L,
conf_level = 0.95,
target = c("sampled_days", "mean_day")
)Arguments
- design
A
creel_design()object withdesign_type == "aerial"and counts attached viaadd_counts(). The counts data must contain the time-of-flight column specified bytime_col.- time_col
Unquoted name of the numeric column in
design$countsrecording the hour of each aerial overflight (e.g.,time_of_flight).- formula
Optional. A formula for the GLMM, passed directly to
lme4::glmer.nb()orlme4::glmer(). IfNULL(default), the Askey (2018) quadratic formula is used:count ~ poly(time_col, 2) + (1 | date).- family
Optional. A family object or character string specifying the GLM family. If
NULLor"negbin"(default),lme4::glmer.nb()is used. Otherwise,lme4::glmer()is called with the specified family.- boot
Logical. If
TRUE, uselme4::bootMer()for parametric bootstrap confidence intervals instead of the delta method. DefaultFALSE.- nboot
Integer. Number of bootstrap replicates when
boot = TRUE. Default500L.- conf_level
Numeric confidence level for the CI. Default
0.95.- target
Character string giving the temporal basis of the returned estimate.
"sampled_days"(default) expands the fitted day to every day the design sampled, matching whatestimate_effort()returns for the same design so the two are comparable."mean_day"reports a single average day, which is what this function returned before tidycreel 7.1.0.Both are expectations, so both carry the retransformation factor described under Details. Neither expands beyond the sampled days: expanded targets are not supported for aerial designs by
estimate_effort()either.
Value
A creel_estimates object with:
estimate: total angler effort integrated over the fishing dayse: standard error (delta method or bootstrap SD)se_between: same asse(fixed-effect SE component)se_within: alwaysNA_real_— no Rasmussen within-day decomposition is performed for GLMM estimatesci_lower,ci_upper: confidence interval bounds, andNA_real_wheneverseis, on both the delta and bootstrap paths. If the visibility correction or the angler-to-people ratio was declared unknown, the total's uncertainty was never fully propagated, so no unconditional interval exists to report. Reporting the remaining spread would be an interval conditional on the unknown multiplier being exact – indistinguishable from declaring it known with zero uncertainty, which is precisely the confusionNAexists to prevent.n: number of count observations used to fit the modelmethod:"aerial_glmm_total"
Details
The fitted curve is a fixed-effects prediction: the day whose random
intercept is zero. On a log link that is the median day rather than the
mean one, so summing it across days would understate the total. Both targets
therefore carry a factor of exp(sigma^2 / 2), where sigma^2 is the
day-level intercept variance — 4% on the package's own fixture, and larger
where days vary more.
That factor treats sigma^2 as known. The reported standard error scales
with the expansion but does not carry the uncertainty in the variance
component itself, so it is mildly optimistic; quantifying that would need a
variance method neither the delta nor the bootstrap path offers today.
References
Askey, P.J., Ward, H., Godin, T., Boucher, M., and Northrup, S. (2018). Angler effort estimates from instantaneous aerial counts: use of high-frequency time-lapse camera data to inform model-based estimators. North American Journal of Fisheries Management, 38, 194-209. doi:10.1002/nafm.10010
See also
Other "Estimation":
compare_cpue_estimators(),
est_age_distribution(),
est_biomass(),
est_compliance(),
est_effort_camera_mi(),
est_length_distribution(),
est_mean_age(),
est_mean_length(),
estimate_catch_rate(),
estimate_effort(),
estimate_harvest_rate(),
estimate_release_rate(),
estimate_total_catch(),
estimate_total_harvest(),
estimate_total_release()
Examples
data(example_aerial_glmm_counts)
aerial_cal <- unique(example_aerial_glmm_counts[, c("date", "day_type")])
aerial_cal <- aerial_cal[order(aerial_cal$date), ]
design <- creel_design(
aerial_cal,
date = date,
strata = day_type,
survey_type = "aerial",
visibility_correction = "none",
angler_ratio = 1,
angler_ratio_se = 0,
h_open = 14
)
design <- add_counts(design, example_aerial_glmm_counts, count_col = n_anglers)
#> Warning: `counts` has 36 repeated sampling units, with no count time to tell them apart.
#> ℹ The repeated rows are keyed on date and day_type.
#> ℹ Estimators that sum these rows refuse them; supply `count_time_col` if they
#> are repeat counts, or `unit_cols` if they are distinct units.
#> Warning: No weights or probabilities supplied, assuming equal probability
# Default Askey quadratic model with delta-method SE
result <- estimate_effort_aerial_glmm(design, time_col = time_of_flight)
#> Warning: iteration limit reached
#> ℹ Integration window start derived from data: 6.5 h (earliest flight - 0.5 h).
#> Specify `open_start` in `creel_design()` for a fixed fishery opening time.
print(result)
#>
#> ── Creel Survey Estimates ──────────────────────────────────────────────────────
#> Method: aerial_glmm_total
#> Variance: delta
#> Confidence level: 95%
#> Effort target: sampled_days
#> model: 412 (known, but se is `NA`)
#> visibility: NA (unknown, so se is `NA`)
#> angler_ratio: 0 (known, but se is `NA`)
#>
#> # A tibble: 1 × 7
#> estimate se se_between se_within ci_lower ci_upper n
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <int>
#> 1 4729. NA NA NA NA NA 48
# Bootstrap CIs. `nboot` is held low here so the example stays fast on a
# check machine; use at least 1000 replicates for real inference. The block
# is wrapped in \donttest{} for runtime alone -- it needs no resource the
# example cannot reach.
# \donttest{
result_boot <- estimate_effort_aerial_glmm(
design,
time_col = time_of_flight,
boot = TRUE,
nboot = 25L
)
#> Warning: iteration limit reached
#> ℹ Integration window start derived from data: 6.5 h (earliest flight - 0.5 h).
#> Specify `open_start` in `creel_design()` for a fixed fishery opening time.
#> Running 25 bootstrap replicates via lme4::bootMer...
#> Warning: ! Bootstrap SE ignores design strata ("day_type").
#> ℹ The default GLMM formula has no stratum term; bootstrap resamples from a
#> single pooled model. Include strata in `formula` for stratified inference.
print(result_boot)
#>
#> ── Creel Survey Estimates ──────────────────────────────────────────────────────
#> Method: aerial_glmm_total
#> Variance: Bootstrap
#> Confidence level: 95%
#> Effort target: sampled_days
#> model: NA (unknown, so se is `NA`)
#>
#> # A tibble: 1 × 7
#> estimate se se_between se_within ci_lower ci_upper n
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <int>
#> 1 4729. NA NA NA NA NA 48
# }