Skip to contents

Check consistency of response options across survey iterations

Usage

check_response_consistency(var, vars_df, dicts_df)

Arguments

var

A string specifying the variable (concept) to check. Must be present in the concept column of vars_df.

vars_df

A data frame mapping each survey iteration to the variable name used for the concept. Expected columns:

  • concept: the concept identifier for each row (matched against var)

  • variable_<cycle>: one column per iteration to include in the comparison, where <cycle> matches a value in the cycle column of dicts_df; each cell holds the variable name used for the concept in that iteration. At least two variable_<cycle> columns are required.

dicts_df

A nested data frame linking each survey iteration to its data dictionary. Expected columns:

  • cycle: the survey iteration identifier

  • dict: a list-column whose elements are iteration-specific data dictionaries (each a data frame)

Each data dictionary should contain the columns:

  • variable: variable name

  • name: value code

  • missing: whether the value is a missing value placeholder

  • label: value label

Value

A logical. TRUE if response options are identical across all iterations, FALSE otherwise. Options are considered identical when, for the given concept, the value code-label pairs (name and label) match across every iteration. If the concept appears in fewer than two iterations, NA is returned (with a warning).

Details

When working with longitudinal survey data, variables representing the same concept (e.g., marital status) may have different response options across iterations. Categories may be added, removed, or relabelled from one iteration to the next. This function helps researchers identify such inconsistencies before combining or comparing data across time points.

In the context of the CLSA, if a researcher is working with two cohorts at three time points, response options across six cohort-iteration combinations should be compared before performing downstream analysis.

Labels that differ only in case or trailing whitespace are treated as not identical. Note that the comprehensiveness of this check depends on the accuracy of the data dictionary. If the data dictionary fails to define all response options in the data, the assessment will be incomplete.

Examples

vars_df <- data.frame(
  concept = "RET_RTRD",
  variable_COM = "RET_RTRD_COM",
  variable_COF1 = "RET_RTRD_COF1",
  variable_COF2 = "RET_RTRD_COF2"
)

dict_a <- data.frame(
  name = c(1:3, 8, 9),
  missing = c(rep(0, 3), rep(1, 2)),
  label = c(
    "Completely retired",
    "Partially retired",
    "Not retired",
    "[DO NOT READ] Don't know/No answer",
    "[DO NOT READ] Refused"
  )
)

dict_b <- data.frame(name = 4, missing = 0, label = "Never had a job")

dict_COM <- dict_a |> dplyr::mutate(variable = "RET_RTRD_COM")
dict_COF1 <- rbind(dict_a, dict_b) |>
  dplyr::mutate(variable = "RET_RTRD_COF1")
dict_COF2 <- rbind(dict_a, dict_b) |>
  dplyr::mutate(variable = "RET_RTRD_COF2")

# tibble allows list-columns natively
dicts_df <- tibble::tibble(
  cycle = c("COM", "COF1", "COF2"),
  dict = list(dict_COM, dict_COF1, dict_COF2)
)

# COM is missing "Never had a job", so response options are inconsistent --> FALSE
check_response_consistency("RET_RTRD", vars_df, dicts_df)
#> [1] FALSE