
Combine disjoint count frames into one stratified survey design
Source:R/hybrid-design.R
as_hybrid_svydesign.RdUsage
as_hybrid_svydesign(
counts,
frame_col,
calendar = NULL,
date_col = "date",
strata_col = "day_type",
count_col = "count",
fraction = NULL,
trips_disjoint = NULL,
fpc = TRUE
)Arguments
- counts
Data frame of count observations for every frame, in long form: one row per frame per sampled date. Must contain the columns named by
date_col,strata_col,count_colandframe_col, with at most one row per frame per date within a stratum.- frame_col
Character scalar. Name of the column in
countsthat partitions it into disjoint count frames – an angler-type column, for instance. Required, with no default: the column carries the partition the whole design rests on, and a default would let a missed argument pick one silently. Must have at least two distinct non-missing values; its values become the frame labels in the returned design.- calendar
Data frame giving the population of days the totals expand to, carrying the columns named by
date_colandstrata_col. Required: theNULLdefault is rejected, and exists only so the error can say what is missing.The stratum population size \(N_h\) is the number of distinct dates the stratum holds, counted the way
creel_design()counts it. One row per day is the natural form, but a duplicated row is tolerated rather than refused, precisely because the count is over distinct dates and a repeat changes nothing.Two things are required. Every sampled date must appear in
calendarunder the same stratum, or the population is smaller than the sample. And each date must belong to exactly one stratum – a day listed under two lengthens the season by a day in each, and the period total then expands to a calendar larger than the one that exists.- date_col
Character scalar. Name of the date column (shared by
countsandcalendar). Default"date". Used to cluster observations into PSUs. Must be of classDate, with no missing values in either table.- strata_col
Character scalar. Name of the stratum column (shared by
countsandcalendar). Default"day_type". Must have no missing values in either table: dates and strata are the join keys, and a missing key matches every other missing key rather than being refused.- count_col
Character scalar. Name of the count column in
counts. Default"count".- fraction
Named list of named numeric vectors, one element per frame, named by the frame labels in
frame_col. Each element gives the within-day sampling fraction per stratum for that frame: the proportion of the frame the count enumerated on each sampled day, in (0, 1]. Expands a sampled day to a whole day; it is not a fraction of the season and does not drive the finite-population correction. Names of each element must match the stratum values that frame carries.- trips_disjoint
Logical scalar. Required: the
NULLdefault is rejected, and exists only so the error can say what is missing. Set toTRUEto affirm that the frames sample disjoint sets of angler trips, the precondition under which their totals may be added. tidycreel cannot verify this from the data; see the "Disjointness precondition" section above.- fpc
Logical scalar. Apply the day-level finite-population correction \(n_h / N_h\)? Default
TRUE. Set toFALSEfor the conservative with-replacement variance.NAand vectors of length other than one are refused.
Value
A survey::svydesign object with an additional class attribute
"creel_hybrid_svydesign". The design data carries the frame_col
column unchanged, a weight column holding both the within-day and the
day-to-season expansion, a .hybrid_stratum column holding the
stratum-by-frame interaction the design is stratified on, and a .pop_days
column holding the stratum population \(N_h\) the finite-population
correction is taken against. attr(design, "component_col") names the
frame column.
Details
Combines two or more count series covering disjoint parts of one fishery into
a single survey::svydesign object. The frames are treated as strata,
each carrying its own within-day sampling fraction, and all expanded to the
same population of days, so the design total is the stratified sum of the
frame totals over the season.
Estimand. The design estimates a period total – the total over
every day in calendar, not over the days that happened to be sampled.
Two expansions get it there, and both live in the row weight: the
within-day fraction expands the part of the frame that the count enumerated
to the whole of it, and N_h / n_h expands the sampled days to the days the
stratum holds. Only the second is a stage-1 sampling fraction, so only the
second drives the finite-population correction.
Disjointness precondition. Adding the frame totals is valid if and only
if the frames sample disjoint sets of angler trips – no angler trip may
be observed by more than one. What produces that disjointness is a property
of the survey protocol (angler type, geography, access mode, or a rule the
designer imposes); tidycreel cannot infer it from the counts, the dates, the
strata, or the frame labels, so you must affirm it with
trips_disjoint = TRUE. The design cannot be constructed otherwise. A boat
angler intercepted on the water by a roving route and again at the ramp on
the same trip belongs to two frames, and the total double counts that trip.
What a frame is. A frame is a disjoint part of the fishery, enumerated
by its own count. In the protocol this design was built for the frames are
angler-type domains – boat anglers, and bank anglers dispersed along a
shoreline with no well-defined access site (Malvestuto 1996). Pope et al.
(Chapter 17) carry exactly this as an anglerType column alongside the
stratum, and estimate effort by stratum and angler type; frame_col is that
column.
The frame is not an interview mode. In the creel literature access and
roving describe how anglers are interviewed: access interviews intercept
completed trips as anglers leave, roving interviews intercept incomplete
trips while anglers are still fishing, and the two require different
catch-rate estimators (Pollock et al. 1994). A survey mixing the two is a
hybrid interview design. Counts are not described that way at all –
they are instantaneous, progressive, bus-route, camera or aerial, the values
creel_schema() accepts for survey_type. tidycreel carries the interview
axis on add_interviews()'s interview_type argument, which is where it
belongs. Earlier versions of this function named its arguments
access_data and roving_data, which borrowed the interview vocabulary for
something that is not an interview mode (GH #248).
Estimation route. The returned object is a survey.design2, not a
creel_design(), so estimate_effort() does not accept it. Estimate from
it with survey::svytotal() and the other survey functions directly, as
in the examples below.
Design structure. Rows are stratified on the interaction of
strata_col and frame_col, so each count frame carries its own
sampled-day count at its own within-day fraction, and clustered on
date_col, so the date is the primary sampling unit. The population size is
taken from calendar and is shared by every frame: one stratum is one span
of the season, whichever frame observed it. A frame that sampled only one
date within a stratum leaves that stratum with a single PSU: the design still
constructs, but survey refuses to compute a variance for it.
One count row per frame-day. A day-level expansion is only defined when a sampled day is one row per frame, so repeated counts on one date within a frame are refused. Two counts on a date are two looks at that date, not two sampled days; summed, they multiply the total by the number of counts, and the day expansion then multiplies that again. Average them to one row per date before constructing the design, or model them on a path that keeps the count time.
PSU alignment requirement: every frame should sample the same date-stratum combinations. A warning is issued when coverage is asymmetric, because the frames should sample the same days. That is a requirement about when each frame samples, not where – frames covering different water is the condition that makes their sum valid, not a source of bias.
See also
Other "Survey Design":
add_catch(),
add_counts(),
add_interviews(),
add_lengths(),
add_sections(),
as_creel_svydesign(),
compute_angler_effort(),
compute_effort(),
creel_design(),
creel_schema(),
creel_vocabulary(),
derive_angler_count(),
est_effort_camera(),
impute_camera_counts(),
mean_party_size(),
prep_counts_boat_party(),
prep_counts_daily_effort(),
prep_interview_catch(),
prep_interviews_trips(),
validate_creel_schema()
Examples
calendar <- data.frame(
date = seq(as.Date("2024-06-01"), as.Date("2024-06-30"), by = "day")
)
calendar$day_type <- ifelse(
format(calendar$date, "%u") %in% c("6", "7"), "weekend", "weekday"
)
counts <- data.frame(
date = rep(
as.Date(c("2024-06-03", "2024-06-04", "2024-06-08", "2024-06-09")),
times = 2
),
day_type = rep(c("weekday", "weekday", "weekend", "weekend"), times = 2),
angler_type = rep(c("boat", "bank"), each = 4),
count = c(12L, 15L, 30L, 28L, 8L, 10L, 22L, 25L)
)
design <- as_hybrid_svydesign(
counts,
frame_col = "angler_type",
calendar = calendar,
fraction = list(
boat = c(weekday = 0.5, weekend = 0.5),
bank = c(weekday = 0.4, weekend = 0.4)
),
trips_disjoint = TRUE
)
# estimate_effort() does not accept this object; use survey directly
survey::svytotal(~count, design)
#> total SE
#> count 2157.5 83.277