
Estimate angler effort from camera/time-lapse count data
Source:R/est-effort-camera.R
est_effort_camera.RdEstimates total angler-hours from a camera-based creel survey design. Two estimation modes are supported:
Usage
est_effort_camera(
design,
interviews = NULL,
effort_col = "hours_fished",
n_anglers = NULL,
intercept_col = NULL,
h_open = NULL,
calibration = NULL,
variance = c("taylor", "replicate"),
conf_level = 0.95
)Arguments
- design
A
creel_designobject created withcreel_design(..., survey_type = "camera")and counts attached viaadd_counts().- interviews
Optional data frame of angler interview records for ratio calibration. Must contain
effort_coland every column indesign$strata_cols: the calibration ratio is estimated within each stratum the design declares, so a missing stratum column is an error rather than a coarser calibration. WhenNULL, falls back to raw count expansion andh_openis required.- effort_col
Character scalar. Column in
interviewscontaining per-trip effort in hours. Default"hours_fished".- n_anglers
Optional party size for the ratio-calibration path. Either a character scalar naming a column in
interviews, or a single positive number stating a constant party size (n_anglers = 1for individual-level interviews).The calibration ratio cancels the camera counts, so the estimate inherits whatever unit
effort_colholds. Supplyingn_anglersmakes this function perform the party-size multiplication, so the result is angler-hours and is labelled as such. Omitting it leaves the estimate in the unit of the column you supplied, which the package cannot identify: the unit is reported as unknown and a warning names the ambiguity. DefaultNULL.- intercept_col
Character scalar or
NULL. Column in the count data representing the camera count during the interview interception period. DefaultNULL(auto-detects the first numeric count column).- h_open
Numeric scalar. Fishable hours per day. Required when
interviews = NULL. DefaultNULL.- calibration
Pass the string
"none"to run the raw-count expansion path without any calibration. Required to reach that path, because expanding a raw camera count byh_openalone silently assumes each counted object contributes exactly one angler-hour per hour open — a calibration of 1 that was never measured (GH #158).Under the opt-out the point estimate uses that assumption and the reported SE is
NA: thecalibrationcomponent is present-and-unknown rather than absent, because the correction applies and was simply not measured. It is never0, which would be indistinguishable from having propagated the calibration's uncertainty and found none.Supplying
interviewsinstead uses the ratio-calibration path, which estimates hours of effort per camera count per stratum and propagates that ratio's variance. Prefer it whenever interview data exist.- variance
Character. Variance method:
"taylor"(default) or"replicate".- conf_level
Numeric confidence level. Default
0.95.
Value
A creel_estimates object with columns estimate, se,
se_between, se_within, ci_lower, ci_upper, n.
Details
Ratio calibration (recommended, when interview data are available): Per-stratum calibration ratios (mean interview effort / mean camera count during the interview period) scale raw camera counts to angler-hours. Variance is estimated via Taylor linearisation or replicate weights.
Raw count expansion (fallback): Camera ingress counts are multiplied by
h_open(fishable hours per day). Use when no interview data are available.
Uncertainty the standard error does not cover
Two cases are reported rather than absorbed, because in both the returned standard error would otherwise understate what is known:
A stratum with a single paired interview/count day gives its calibration ratio no measurable spread. That variance is unknown rather than zero, so it is carried as
NAand the combined standard error and confidence interval areNAtoo; a warning names the stratum. Add a second matched interview day in that stratum to recover a standard error.Counts flagged
.imputedbyimpute_camera_counts()enter the estimator as observations. The imputation model's prediction uncertainty is not propagated, and model predictions vary less than real counts, so the between-day component is understated as well. A warning reports how many days were imputed; the standard error is a lower bound.
Within-day variance
When counts arrive through add_counts(count_time_col = ), several counts
on one day are averaged into a daily mean and the within-day components
(ss_d, k_d) are stored on the design. Both paths of this function read
them and report the Rasmussen (1998) within-day term as se_within,
scaling it by the stratum's calibration ratio on the ratio path and by
h_open on the raw path.
se_within is 0 only when there is genuinely nothing to measure – one
count per day, where the component is nil by construction rather than
unknown. It was previously reported as a literal 0 in every case, while
the measured components sat unread on the design, so a design with real
within-day spread received the same standard error as one with none.
One count row per day on the calibration path
Ratio calibration pairs each interview day to that day's camera count, so it requires the counts table to hold exactly one row per day (per stratum). A repeated day is refused rather than averaged: two counts on one date are either sub-period snapshots or a data error, and the estimator cannot tell which. Before this was checked, a repeated date entered both sides of the calibration ratio twice and moved the point estimate, not merely the standard error.
If the counts are genuine sub-daily observations, pass count_time_col to
add_counts(), which averages them into one row per day and retains the
within-day variance. Otherwise remove the repeated rows. Raw count expansion
(interviews = NULL) does no pairing and is not subject to this requirement.
Where the calibration estimator comes from
The ratio calibration is a double-sampling ratio estimator, applied here to camera calibration by this package. It is not a reproduction of a published fisheries estimator, and no paper in the camera literature derives it in this form.
Within each stratum the estimator forms rho as a ratio of sums –
interview hours over camera counts on the paired days – estimates its
variance by the ratio-estimator formula on the paired daily residuals, and
applies it to that stratum's first-phase count total, combining the two
variances by the delta method. The counts are the first-phase sample and the
days carrying interviews are the second phase, which is the structure
Cochran (1977) Chapter 12 treats; the ratio's variance is Cochran's
eq. 2.46 with the finite-population correction omitted.
The practice of calibrating camera counts against paired concurrent creel observations is well established – Hartill et al. (2016), van Poorten et al. (2015), Eckelbecker et al. (2022) – but each of those uses a different estimator: a per-day classification proportion, a hierarchical Bayesian model, and a fitted linear correction respectively. Hartill et al. (2020) is a review of camera monitoring and presents no estimator or variance at all.
In particular this is not Hartill et al.'s (2016) rho. Theirs is the
dimensionless proportion of observed boats that were fishing, estimated per
day from interviews that are a subsample of the camera's own frame, with a
bootstrap variance. The ratio here has units of hours per count, corrects
counts to effort rather than classifying them, pools over days within a
stratum, and pairs the camera against an independent measurement – a
different variance structure, which is why a design-based ratio variance is
used rather than a bootstrap.
References
Cochran, W.G. 1977. Sampling Techniques, 3rd ed. Wiley, New York. Section 2.11 gives the ratio estimator and its estimated variance (eq. 2.46), which is the form used here with the finite-population correction omitted. Chapter 12 covers double sampling, and Section 12.9 (p. 343) the ratio estimator applied to a first-phase total.
Hartill, B.W., Payne, G.W., Rush, N., and Bian, R. 2016. Bridging the temporal gap: continuous and cost-effective monitoring of dynamic recreational fisheries by web cameras and creel surveys. Fisheries Research 183:488-497. doi:10.1016/j.fishres.2016.06.002
van Poorten, B.T., Carruthers, T.R., Ward, H.G.M., and Varkey, D.A. 2015. Imputing recreational angling effort from time-lapse cameras using an hierarchical Bayesian model. Fisheries Research 172:265-273. doi:10.1016/j.fishres.2015.07.032
Eckelbecker, R.W., Coleman, T.S., and Catalano, M.J. 2022. Incorporating time-lapse digital cameras into creel surveys at three Alabama reservoirs. North American Journal of Fisheries Management 42:1349-1358. doi:10.1002/nafm.10828
Hartill, B.W., Taylor, S.M., Keller, K., and Weltersbach, M.S. 2020. Digital camera monitoring of recreational fishing effort: applications and challenges. Fish and Fisheries 21:204-215. doi:10.1111/faf.12413
See also
Other "Survey Design":
add_catch(),
add_counts(),
add_interviews(),
add_lengths(),
add_sections(),
as_creel_svydesign(),
as_hybrid_svydesign(),
compute_angler_effort(),
compute_effort(),
creel_design(),
creel_schema(),
creel_vocabulary(),
derive_angler_count(),
impute_camera_counts(),
mean_party_size(),
prep_counts_boat_party(),
prep_counts_daily_effort(),
prep_interview_catch(),
prep_interviews_trips(),
validate_creel_schema()
Examples
library(tidycreel)
data(example_camera_counts)
data(example_camera_interviews)
cal <- data.frame(
date = unique(example_camera_counts$date),
day_type = unique(example_camera_counts[, c("date", "day_type")])[["day_type"]]
)
design <- creel_design(cal,
date = date, strata = day_type,
survey_type = "camera", camera_mode = "counter"
)
# Filter to operational rows
ops <- example_camera_counts[
example_camera_counts$camera_status == "operational",
]
design <- add_counts(design, ops)
#> Warning: No weights or probabilities supplied, assuming equal probability
# Ratio calibration using interview hours. `example_camera_interviews` has no
# party-size column, so this warns and reports an unknown unit: the estimate
# is in whatever unit `hours_fished` holds, which the package cannot tell.
est <- est_effort_camera(design, interviews = example_camera_interviews)
#> Warning: Camera ratio calibration cannot tell angler-hours from party-hours.
#> ✖ hours_fished is a caller-supplied column and nothing on this path normalises
#> it by party size.
#> ℹ Pass `n_anglers` -- a column in `interviews`, or a constant party size -- to
#> make the unit derivable.
#> ℹ The estimate is returned with an unknown unit until then.
print(est)
#>
#> ── Creel Survey Estimates ──────────────────────────────────────────────────────
#> Method: camera_ratio
#> Variance: Taylor linearization
#> Confidence level: 95%
#> Count-sampling SE: 4.277 (included in se)
#> Calibration SE: 11.71 (included in se)
#>
#> # A tibble: 1 × 7
#> estimate se se_between se_within ci_lower ci_upper n
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <int>
#> 1 111. 12.5 12.5 0 81.4 140. 9
# With party sizes the function does the normalisation itself, so the result
# is angler-hours and is labelled as such.
ints <- example_camera_interviews
ints$party_size <- 2
est_ah <- est_effort_camera(design, interviews = ints, n_anglers = "party_size")
print(est_ah)
#>
#> ── Creel Survey Estimates ──────────────────────────────────────────────────────
#> Method: camera_ratio
#> Variance: Taylor linearization
#> Confidence level: 95%
#> Unit: angler-hours
#> Count-sampling SE: 8.555 (included in se)
#> Calibration SE: 23.41 (included in se)
#>
#> # A tibble: 1 × 7
#> estimate se se_between se_within ci_lower ci_upper n
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <int>
#> 1 222. 24.9 24.9 0 163. 281. 9