--- title: "Labels and Missing Values" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Labels and Missing Values} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", message = FALSE, warning = FALSE ) ``` ```{r setup} library(mariposa) library(dplyr) data(survey_data) ``` ## Overview Survey data from SPSS, Stata, and SAS stores two kinds of labels: - **Variable labels** describe what a variable measures (e.g., `gender` → "Respondent's gender") - **Value labels** map numeric codes to text (e.g., `1` → "Male", `2` → "Female") In R, these labels are stored as attributes on `haven_labelled` columns. mariposa provides 10 functions for inspecting, modifying, and converting labelled data --- plus tools for declaring missing values and searching variables. | Function | Purpose | |----------|---------| | `var_label()` | Get or set variable labels | | `val_labels()` | Get or set value labels | | `find_var()` | Search variables by name or label pattern | | `to_label()` | Convert labelled → factor | | `to_character()` | Convert labelled → character | | `to_numeric()` | Convert factor/labelled → numeric | | `to_labelled()` | Convert factor/character → labelled | | `set_na()` | Declare values as missing (tagged NAs) | | `unlabel()` | Strip all label metadata | | `copy_labels()` | Restore labels after dplyr operations | | `drop_labels()` | Remove unused value labels | ## Inspecting Labels ### Variable Labels Variable labels describe what each column contains. Use `var_label()` to retrieve them: ```{r} # Get labels for specific variables var_label(survey_data, gender, education, life_satisfaction) ``` ```{r} # Get labels for all variables var_label(survey_data) ``` ### Value Labels Value labels map numeric codes to meaningful text. Use `val_labels()` to retrieve them: ```{r} # Get value labels for a single variable val_labels(survey_data, gender) ``` ```{r} # Get value labels for multiple variables val_labels(survey_data, education, employment) ``` ### Finding Variables SPSS datasets often have cryptic variable names like `q104a_1` or `v23`. Use `find_var()` to search by name or label: ```{r} # Search in both names and labels (default) find_var(survey_data, "trust") ``` ```{r} # Search only in variable labels find_var(survey_data, "satisfaction", search = "label") ``` ```{r} # Search only in variable names find_var(survey_data, "age|income", search = "name") ``` ## Setting Labels ### Setting Variable Labels ```{r} # Set labels for specific variables labeled_data <- var_label(survey_data, age = "Age of respondent in years", income = "Monthly net income in euros" ) # Verify var_label(labeled_data, age, income) ``` ### Setting Value Labels ```{r} # Set value labels on a numeric (1-5) rating labeled_data <- val_labels(survey_data, life_satisfaction = c("Very dissatisfied" = 1, "Very satisfied" = 5) ) # Verify val_labels(labeled_data, life_satisfaction) ``` ```{r} # Add labels without replacing existing ones labeled_data <- val_labels(labeled_data, life_satisfaction = c("Neither" = 3), .add = TRUE ) val_labels(labeled_data, life_satisfaction) ``` ## Converting Between Formats Survey data often needs conversion between labelled, factor, character, and numeric formats depending on the analysis. ### Labelled → Factor Use `to_label()` when you need factors for plotting or statistical models: ```{r} # Labelled variables become factors (factors such as gender pass through) factor_data <- to_label(survey_data, gender, education) # Check the result class(factor_data$gender) levels(factor_data$gender) head(factor_data$gender) ``` ```{r} # Create ordered factors (useful for ordinal variables) ordered_data <- to_label(survey_data, education, ordered = TRUE) levels(ordered_data$education) ``` ### Labelled → Character Use `to_character()` for string-based operations: ```{r} char_data <- to_character(survey_data, gender, region) head(char_data$gender) ``` ### Factor → Numeric Use `to_numeric()` to convert factors or labelled vectors back to numbers: ```{r} # First convert to factor, then back to numeric factor_data <- to_label(survey_data, education) # Parse numeric values from factor levels numeric_data <- to_numeric(factor_data, education) head(numeric_data$education) ``` ### Numeric/Factor → Labelled Use `to_labelled()` to add labels to plain numeric or factor columns: ```{r} # Convert a factor back to haven_labelled plain_data <- data.frame( gender = factor(c("Male", "Female", "Male")), score = c(3, 4, 2) ) labelled_data <- to_labelled(plain_data, gender) class(labelled_data$gender) ``` ## Declaring Missing Values ### Setting Values as Missing Use `set_na()` to declare specific numeric codes as missing values: ```{r, eval = FALSE} # After importing SPSS data where -9 = refused, -8 = don't know data <- read_spss("survey.sav", tag_na = FALSE) # Declare -9 and -8 as missing across all numeric columns data <- set_na(data, -9, -8, tag = TRUE) # Declare different missing codes for specific variables data <- set_na(data, q1 = c(-9, -8), q2 = c(99)) ``` When `tag = TRUE` (the default), each missing code becomes a distinct tagged NA, so you can later distinguish "refused" from "don't know" responses. ### Removing All Labels Use `unlabel()` when you need plain numeric data without any label metadata: ```{r, eval = FALSE} # Strip all labels from entire dataset plain_data <- unlabel(survey_data) # Strip labels from specific variables only plain_data <- unlabel(survey_data, gender, education) ``` This converts `haven_labelled` columns to plain `numeric` or `character`, tagged NAs to regular `NA`, and removes all label attributes. ## Preserving Labels Through Pipelines ### The Problem dplyr operations like `filter()`, `mutate()`, and `select()` can strip label attributes from columns: ```{r} filtered <- survey_data %>% filter(age >= 30) %>% select(gender, education, income) # Labels may be lost after certain operations ``` ### The Solution: copy_labels() Use `copy_labels()` to restore labels from the original data: ```{r} # Restore labels from the source dataset filtered <- copy_labels(filtered, survey_data) # Verify labels are back var_label(filtered, gender, education) ``` ### Cleaning Unused Labels After filtering, some value label categories may no longer appear in the data. Use `drop_labels()` to clean them up: ```{r} # Subset to one region only subset_data <- survey_data %>% filter(region == 1) # Remove value labels for regions that are no longer in the data clean_data <- drop_labels(subset_data, region) val_labels(clean_data, region) ``` ## Complete Example A typical workflow for preparing SPSS data for analysis: ```{r, eval = FALSE} # 1. Import SPSS file data <- read_spss("survey_2024.sav") # 2. Explore what's in the data codebook(data) find_var(data, "satisf") find_var(data, "trust") # 3. Check labels var_label(data, q1, q2, q3) val_labels(data, q1) # 4. Rename variables for clarity data <- data %>% rename(life_satisfaction = q1, income = q2, education = q3) # Update variable labels data <- var_label(data, life_satisfaction = "Overall life satisfaction (1-5)", income = "Monthly net income in euros", education = "Highest education level" ) # 5. Convert categorical variables for analysis data <- to_label(data, education, gender) # 6. Analyze data %>% describe(life_satisfaction, income, weights = sampling_weight) data %>% t_test(life_satisfaction, group = gender, weights = sampling_weight) ``` ## Practical Tips 1. **Keep labels as long as possible.** Labels carry important context. Only convert to factor or character when a specific function requires it. 2. **Use `find_var()` instead of `names()`.** It searches both names and labels, which is essential for SPSS datasets with non-descriptive variable names. 3. **Use `copy_labels()` after complex pipelines.** If your pipeline involves joins, reshaping, or other operations that might strip attributes, restore labels from the original data. 4. **Prefer `to_label()` over `as.factor()`.** `to_label()` uses the value labels as factor levels, giving you meaningful names instead of numeric codes. 5. **Use `set_na()` early in your workflow.** Declaring missing values immediately after import ensures they are handled correctly in all downstream analyses. ## Summary 1. `var_label()` and `val_labels()` get and set variable and value labels 2. `find_var()` searches variables by name or label pattern 3. `to_label()`, `to_character()`, `to_numeric()`, `to_labelled()` convert between formats 4. `set_na()` declares values as missing; `unlabel()` strips all metadata 5. `copy_labels()` restores labels after dplyr operations; `drop_labels()` cleans up unused labels ## Next Steps - Transform and recode variables --- see `vignette("data-transformation")` - Import data from SPSS, Stata, and SAS --- see `vignette("data-io")` - Start analyzing your data --- see `vignette("descriptive-statistics")`