---
title: "Where fieldopt applies: beyond agricultural surveys"
output:
  rmarkdown::html_vignette:
    css: fieldopt.css
vignette: >
  %\VignetteIndexEntry{Where fieldopt applies: beyond agricultural surveys}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

<!-- Generated from applications.Rmd.orig by tools/precompute-vignettes.R; edit the .orig file. -->



The package was built for agricultural surveys with an area frame, but its
pieces are general: a probability sample of places, the cost of visiting
them, and the estimate that comes out. Any survey that sends people to
locations fits. Four settings, each with the functions it uses.

| Setting | Units | Balanced on | Field constraint | Main functions |
|-----------------|-------------|---------------|---------------|-------------------|
| Agricultural area frame | grid cells, points | space, intensity | team-days, service per cell | all (plan vignette) |
| Environmental monitoring | sites (lakes, plots, stations) | space, covariates | daily range of boats or vehicles | `select_units(method = "cube")`, `route_fieldwork()` |
| Household survey | enumeration areas, then households | population size | interviewer-days, several offices | `two_stage_allocation()`, `schedule_fieldwork(region = )` |
| Establishment survey | listed firms plus area segments | coverage of the unlisted | screening in the field | `frame_overlap()`, `dual_frame_allocation()`, `dual_frame_estimator()` |

## Environmental monitoring: sites balanced on covariates

Three hundred candidate lakes with altitude and surface; the monitoring
programme can visit forty a season with two boats, each out for at most ten
hours a day including four hours of sampling per lake. The cube method
balances the sample on the covariates while the routes keep the days
feasible.


``` r
set.seed(31)
lakes <- tibble(
  unit = paste0("lake", 1:300),
  x = runif(300, 0, 200), y = runif(300, 0, 120)
) |>
  mutate(altitude = 200 + 8 * y + rnorm(n(), sd = 40), surface = exp(rnorm(n(), 2, 0.8)))
s <- lakes |>
  select_units(n = 40, method = "cube", balance = c("altitude", "surface"), seed = 2)
bind_rows(frame = lakes, sample = sampled(s), .id = "set") |>
  group_by(set) |>
  summarise(across(c(altitude, surface), mean))
#> # A tibble: 2 × 3
#>   set    altitude surface
#>   <chr>     <dbl>   <dbl>
#> 1 frame      685.    10.2
#> 2 sample     674.    10.3
harbour <- tibble(unit = "harbour", x = 100, y = 0)
r <- s |>
  travel_matrix(bases = harbour, method = "euclidean", speed = 60) |> # 60 km/h: minutes
  route_fieldwork(
    units = s, depot = "harbour",
    max_length = 600, service_time = 240, iterations = 100
  )
tibble(days = r$n_routes, longest_day = round(max(r$durations)))
#> # A tibble: 1 × 2
#>    days longest_day
#>   <int>       <dbl>
#> 1    36         598
```

## Household survey: enumeration areas from several offices

Enumeration areas are selected with probability proportional to their
households, then a fixed number of households inside each; the two-stage
allocation says how many of each, and the schedule assigns the areas to the
regional offices and their interviewers.


``` r
set.seed(5)
ea <- tibble(unit = paste0("ea", 1:400), x = runif(400, 0, 60), y = runif(400, 0, 40)) |>
  mutate(households = round(exp(rnorm(n(), 5, 0.4))))
two_stage_allocation(
  n_primary = 400, m_secondary = mean(ea$households), s2_between = 0.04, s2_within = 0.22,
  c1 = 350, c2 = 18, target_cv = 0.03, mean = 0.4
)
#> 
#> ── Two-stage allocation ────────────────────────────────────────────────────────
#> n = 249 primary units with m = 10 secondary units each (optimal m 10.52): cost
#> 132000, variance of the total 621600 (SE 788.4, CV 3%).
offices <- tibble(unit = c("office_w", "office_e"), x = c(12, 48), y = c(20, 20))
s <- ea |> select_units(n = 36, size = "households", seed = 9)
sch <- s |>
  travel_matrix(bases = offices, method = "euclidean", speed = 20) |> # 20 km/h: minutes
  schedule_fieldwork(
    units = s, teams = c(office_w = 3, office_e = 2), days = 10,
    max_length = 480, service_time = 300, iterations = 60
  )
sch$summary
#> # A tibble: 2 × 7
#>   base     units teams routes days_needed days_available fits 
#> * <chr>    <int> <dbl>  <int>       <int>          <dbl> <lgl>
#> 1 office_w    18     3     18           6             10 TRUE 
#> 2 office_e    18     2     18           9             10 TRUE
```

## Establishment survey: a list and an area frame

A register covers the large establishments but misses the small and the
new ones; an area frame covers everything but is expensive. The dual-frame
design samples both, sizes them for the money available, and the estimator
combines the two samples. The dual-frame vignette shows the estimation; the
allocation below spends a budget between the frames.


``` r
domains <- tibble(
  domain = c("a", "ab", "b"), size = c(5000, 800, 150),
  mean = c(12, 90, 110), sd = c(10, 60, 70)
)
dual_frame_allocation(domains, cost_a = 220, cost_b = 35, deff_a = 1.6, budget = 150000)
#> 
#> ── Dual-frame allocation ───────────────────────────────────────────────────────
#> Minimum variance for budget 150000: n_A = 530 (frame A, cost 220/unit), n_B =
#> 950 (frame B, cost 35/unit), theta = 0.088 (optimised).
#> Cost 149800; variance 8492000 (frame A 8490000, frame B 0); CV 1.96% of the
#> total 148500.
#> Expected overlap units: 73.1 in the A sample, 800 in the B sample; a bound on a
#> sample size was active.
```

## What stays the same across settings

Every setting goes through the same objects: a frame with coordinates, a
`fieldopt_sample` with known inclusion probabilities, a travel matrix, a
`fieldopt_routes` or `fieldopt_schedule`, and a one-row tibble with the
estimate and its variance. The cost side (`field_cost_model()`,
`cost_variance_frontier()`) and the connectors to `survey`, `sf`, OSRM,
`vrpr` and `highs` are the same too.
