Skip to contents

Introduction

Aerial creel surveys estimate total angler effort by conducting an instantaneous count of anglers on the water from a low-flying aircraft. Because the aircraft captures a snapshot of angler activity at a single moment, the count must be expanded to total effort using the hours the fishery is open (h_open) and the mean trip duration of anglers on the water (L_bar). The basic estimator is:

Ê=Nobs×hopenv\hat{E} = N_{obs} \times \frac{h_{open}}{v}

where NobsN_{obs} is the observed (instantaneous) angler count, hopenh_{open} is the number of hours the fishery is open per day, and vv is the detection probability — the proportion of anglers present that are detected from the aircraft. The mean trip duration L\bar{L} is estimated from ground interviews and enters the catch rate estimation step rather than the effort expansion step.

When not all anglers are visible from the air — for example, anglers fishing under tree cover or in enclosed shelters — a visibility correction adjusts the count upward. If observers detect only 85% of anglers present, the corrected effort estimate is scaled by 1/0.851.181 / 0.85 \approx 1.18, yielding a higher and more accurate total. The visibility_correction argument to creel_design() carries vv, and is required for an aerial design: pass "none" to state explicitly that no correction applies.

vv is the reciprocal of the published ratio

Field studies do not report vv directly. The standard ground-truthing method reports the ratio

r=ground countaerial countr = \frac{\text{ground count}}{\text{aerial count}}

which is greater than 1 whenever the aircraft undercounts — Smucker et al. (2010) report r=2.69r = 2.69 for shore anglers. Because visibility_correction is a probability, convert before supplying it:

v=1/rsor=2.69v=0.372v = 1 / r \qquad\text{so}\qquad r = 2.69 \;\longrightarrow\; v = 0.372

Passing rr directly is rejected by the (0, 1] check rather than silently accepted, because the two parameterisations differ by a factor of r2r^2 in the effort estimate.

The correction is estimated, so it carries uncertainty

vv is estimated from paired air–ground counts, and the standard field method reports its standard error as routine output. Supply it as visibility_se — on the same probability scale — and that uncertainty is propagated into the effort SE. For an SE published on the ratio scale, convert with SE(v)=SE(r)/r2SE(v) = SE(r) / r^2.

Because one estimate of vv divides every scaled count, it is a shared multiplier: its contribution enters once at the total and does not shrink as more flights are flown. Omitting visibility_se reports the component as absent rather than as zero — a zero would be indistinguishable from never having propagated it at all.

Example Data

This vignette uses two built-in datasets representing a hypothetical summer walleye and bass fishery at a Nebraska reservoir in June-July 2024.

library(tidycreel)

data(example_aerial_counts)
data(example_aerial_interviews)

head(example_aerial_counts)
#>         date day_type n_anglers
#> 1 2024-06-03  weekday        39
#> 2 2024-06-05  weekday        32
#> 3 2024-06-07  weekday        29
#> 4 2024-06-08  weekend        45
#> 5 2024-06-09  weekend        51
#> 6 2024-06-10  weekday        34
head(example_aerial_interviews)
#>         date day_type trip_status hours_fished walleye_catch walleye_kept
#> 1 2024-06-03  weekday    complete          3.4             3            2
#> 2 2024-06-03  weekday    complete          3.2             0            0
#> 3 2024-06-03  weekday    complete          2.5             0            0
#> 4 2024-06-05  weekday    complete          4.9             1            0
#> 5 2024-06-05  weekday    complete          2.2             1            0
#> 6 2024-06-05  weekday    complete          2.3             1            0
#>   bass_catch bass_kept
#> 1          0         0
#> 2          0         0
#> 3          0         0
#> 4          1         0
#> 5          0         0
#> 6          1         1

example_aerial_counts contains 16 sampling days (one overflight per day), each recording an instantaneous count of anglers on the water. Weekday counts range from 15 to 40 anglers; weekend counts range from 40 to 80. The example_aerial_interviews dataset contains 48 angler interviews (3 per sampling day) with trip duration in hours_fished and catch by species.

Design Construction

Build an aerial survey design with creel_design(). The h_open argument is required for aerial surveys — it specifies the number of hours the fishery is open each day, which sets the expansion factor for the instantaneous count.

# Build the survey calendar from the unique count dates
aerial_cal <- data.frame(
  date = example_aerial_counts$date,
  day_type = example_aerial_counts$day_type,
  stringsAsFactors = FALSE
)

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
)

print(design)
#> 
#> ── Creel Survey Design ─────────────────────────────────────────────────────────
#> Type: "aerial"
#> Date column: date
#> Strata: day_type
#> Calendar: 16 days (2024-06-03 to 2024-07-06)
#> day_type: 2 levels
#> Counts: "none"
#> Interviews: "none"
#> Sections: "none"
#> 
#> ── Aerial Survey Design ──
#> 
#> Hours open (h_open): 14
#> Visibility correction: "none" (declared; SE is "NA")
#> Angler-to-people ratio: 1
#> Angler ratio SE: 0

The printed design confirms the survey type, h_open, and the number of sampling days in each stratum.

Adding Count Data and Estimating Effort

Attach the aerial count data with add_counts(). The n_anglers column is auto-detected as the count variable.

design <- add_counts(design, example_aerial_counts)
#> Warning in svydesign.default(ids = psu_formula, strata = strata_formula, : No
#> weights or probabilities supplied, assuming equal probability

Aerial effort estimation requires interview data to be attached before calling estimate_effort(), because the estimator uses the mean trip duration (L\bar{L}) from ground interviews to confirm the expansion factor. Attach the interview data with add_interviews(), then estimate total effort.

design <- suppressWarnings(add_interviews(
  design,
  example_aerial_interviews,
  catch       = walleye_catch,
  effort      = hours_fished,
  trip_status = trip_status
))
#>  Added 48 interviews: 48 complete (100%), 0 incomplete (0%)
effort <- suppressWarnings(estimate_effort(design))
print(effort)
#> 
#> ── Creel Survey Estimates ──────────────────────────────────────────────────────
#> Method: aerial_total
#> Variance: Taylor linearization
#> Confidence level: 95%
#> Effort target: sampled_days
#> Unit: angler-hours
#> Count-sampling SE: 658.3 (known, but se is `NA`)
#> within_day: 0 (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     8918    NA       658.         0       NA       NA    16

The estimate column is the projected total angler-hours over the full survey period, and se_between quantifies between-day variability in the instantaneous counts.

se, ci_lower and ci_upper are NA, and that is the correct output for this design rather than a gap in it. creel_design() above was given visibility_correction = "none", which declares that no detection study was done. The between-day component is known, but a component of the total’s uncertainty is not, and a standard error that silently omitted it would describe a survey more precise than this one. NA says the uncertainty was never propagated; 0 would say it was measured and found to be nothing. The next section supplies a correction and its standard error, and the interval appears.

Visibility Correction

When aerial observers cannot detect all anglers on the water, the raw count underestimates true effort. Supply a visibility_correction to creel_design() to account for this. A value of 0.85 means observers detected 85% of the anglers actually present; the effort estimate is scaled up by 1/0.851 / 0.85.

Here the correction is accompanied by visibility_se, so the reported effort SE includes the uncertainty in the correction itself rather than treating 0.85 as exactly known.

design_corr <- creel_design(
  aerial_cal,
  date = date,
  strata = day_type,
  survey_type = "aerial",
  h_open = 14,
  visibility_correction = 0.85,
  angler_ratio = 1,
  angler_ratio_se = 0,
  visibility_se = 0.04
)

design_corr <- add_counts(design_corr, example_aerial_counts)
#> Warning in svydesign.default(ids = psu_formula, strata = strata_formula, : No
#> weights or probabilities supplied, assuming equal probability
design_corr <- suppressWarnings(add_interviews(
  design_corr,
  example_aerial_interviews,
  catch       = walleye_catch,
  effort      = hours_fished,
  trip_status = trip_status
))
#>  Added 48 interviews: 48 complete (100%), 0 incomplete (0%)

effort_corr <- suppressWarnings(estimate_effort(design_corr))
print(effort_corr)
#> 
#> ── Creel Survey Estimates ──────────────────────────────────────────────────────
#> Method: aerial_total
#> Variance: Taylor linearization
#> Confidence level: 95%
#> Effort target: sampled_days
#> Unit: angler-hours
#> Count-sampling SE: 774.4 (included in se)
#> within_day: 0 (included in se)
#> visibility: 493.7 (included in se)
#> angler_ratio: 0 (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   10492.  918.       774.         0    8522.   12462.    16

Comparing the two estimates: the corrected effort is higher than the uncorrected estimate because the visibility correction inflates the count to account for undetected anglers.

cat(
  "Uncorrected effort:", round(effort$estimate[[1]], 0), "angler-hours\n",
  "Corrected effort (v=0.85):", round(effort_corr$estimate[[1]], 0), "angler-hours\n"
)
#> Uncorrected effort: 8918 angler-hours
#>  Corrected effort (v=0.85): 10492 angler-hours

Interview-Based Catch Estimation

Aerial designs use the same interview workflow as other tidycreel designs. The catch rate estimator computes CPUE (walleye per angler-hour) from the complete-trip interviews already attached to the design.

catch_rate <- suppressWarnings(estimate_catch_rate(design))
#>  Using complete trips for CPUE estimation
#>   (n=48, 100% of 48 interviews) [default]
print(catch_rate)
#> 
#> ── Creel Survey Estimates ──────────────────────────────────────────────────────
#> Method: Ratio-of-Means CPUE
#> Variance: Taylor linearization
#> Confidence level: 95%
#> Unit: fish/party-hour
#> 
#> # A tibble: 1 × 5
#>   estimate     se ci_lower ci_upper     n
#>      <dbl>  <dbl>    <dbl>    <dbl> <int>
#> 1    0.413 0.0601    0.295    0.531    48

estimate_total_catch() multiplies the CPUE estimate by the total effort estimate to project total walleye catch over the survey period.

total_catch <- suppressWarnings(estimate_total_catch(design))
print(total_catch)
#> 
#> ── Creel Survey Estimates ──────────────────────────────────────────────────────
#> Method: Total Catch (Effort × CPUE)
#> Variance: Taylor linearization
#> Confidence level: 95%
#> Effort target: sampled_days
#> 
#> # A tibble: 1 × 5
#>   estimate    se ci_lower ci_upper     n
#>      <dbl> <dbl>    <dbl>    <dbl> <int>
#> 1     251.  45.1     160.     341.    48

The delta-method standard error on total catch accounts for variance in both the effort estimate and the CPUE estimate.

Summary

The complete aerial survey workflow in tidycreel consists of four steps:

  1. creel_design(..., survey_type = "aerial", visibility_correction = v, h_open = N) — define the survey with the required h_open expansion factor and the required visibility_correction (a detection probability, or "none" to declare that no correction applies). Add visibility_se to propagate the correction’s own uncertainty.
  2. add_counts(design, counts) — attach the instantaneous angler count data from each overflight.
  3. add_interviews(design, interviews, catch = ..., effort = hours_fished, ...) — attach ground interview data for catch rate estimation.
  4. estimate_effort(), estimate_catch_rate(), estimate_total_catch() — run the estimators.

All estimators return creel_estimates objects with point estimates, standard errors, and 95% confidence intervals. Use print() to display results.

References

  • Jones, C. M., & Pollock, K. H. (2012). Recreational survey methods: estimation of effort, harvest, and abundance. Chapter 19 in Fisheries Techniques (3rd ed.), pp. 883-919. American Fisheries Society.

  • Malvestuto, S. P. (1996). Sampling the recreational angler. Chapter 20 in Fisheries Techniques (2nd ed.), pp. 591-623. American Fisheries Society.

  • Pollock, K. H., Jones, C. M., & Brown, T. L. (1994). Angler Survey Methods and Their Applications in Fisheries Management. American Fisheries Society Special Publication 25. Chapter 12: Aerial counts.