A proposed helper function to read OD survey data with appropriate weights and strata using {survey}. This function currently works only with São Paulo data. I've tested it only with the 2017 survey, but I'm confident that it should work with other years as well. I assume the user will input a data.frame generated by read_od.
#' Create the survey design for São Paulo's OD data.
#'
#' Create a survey design for São Paulo's OD microdata. Requires the \code{survey}
#' package.
#'
#' @param df A `data.frame` with POD microdata, ideally generated by `read_od`.
#' @param id Choice of identifier. Must be one of `individual` ('pessoa'),
#' `family` ('família), or `household` ('domicílio').
#' @param verbose Logical. If `TRUE` (default), displays validation messages.
#'
#' @return An object of class \code{survey.design} with the appropriate weights and strata.
#' @export
#'
#' @importFrom survey svydesign
#'
#' @examples
#' \dontrun{
#' # Create person-level survey design
#' srv_pess <- design_od(od_data, id = "individual")
#'
#' # Create family-level survey design silently
#' srv_hh <- design_od(od_data, id = "household", verbose = FALSE)
#' }
design_od <- function(df, id, verbose = TRUE) {
# Input validation
if (!is.data.frame(df)) {
cli::cli_abort(c(
"x" = "Input {.arg df} must be a data.frame",
"i" = "You provided an object of class {.cls {class(df)}}"
))
}
# Validate id parameter
valid_ids <- c("individual", "family", "household")
if (!id %in% valid_ids) {
cli::cli_abort(c(
"x" = "Invalid {.arg id} value: {.val {id}}",
"i" = "Must be one of: {.val {valid_ids}}"
))
}
# Define configurations for each survey level
config <- list(
individual = list(
name = "person",
id_col = "id_pess",
weight_col = "fe_pess",
description = "Individual person weights"
),
family = list(
name = "family",
id_col = "id_fam",
weight_col = "fe_fam",
description = "Family-level weights"
),
household = list(
name = "household",
id_col = "id_dom",
weight_col = "fe_dom",
description = "Household-level weights"
)
)
current_config <- config[[id]]
# Check for missing values in critical columns
weight_col <- current_config$weight_col
id_col <- current_config$id_col
# Create survey design
if (verbose) {
cli::cli_alert_info("Creating survey design with {current_config$description}")
}
clean_data <- unique(df, by = id_col)
final_rows <- nrow(clean_data)
tryCatch({
out <- survey::svydesign(
ids = ~ 1,
weights = stats::as.formula(paste("~", weight_col)),
strata = ~ zona,
data = df
)
if (verbose) {
cli::cli_alert_success("Survey design created successfully")
# Summary statistics
n_strata <- length(unique(clean_data$zona))
cli::cli_alert_info("Design summary:")
cli::cli_ul(c(
"Survey type: {.val {current_config$name}}-level",
"Sample size: {.val {final_rows}} observations",
"Strata: {.val {n_strata}} zones"
))
}
return(out)
}, error = function(e) {
cli::cli_abort(c(
"x" = "Failed to create survey design",
"!" = "Error: {e$message}",
"i" = "Check your data structure and column names"
))
})
}
A proposed helper function to read OD survey data with appropriate weights and strata using {survey}. This function currently works only with São Paulo data. I've tested it only with the 2017 survey, but I'm confident that it should work with other years as well. I assume the user will input a
data.framegenerated byread_od.