formr icon indicating copy to clipboard operation
formr copied to clipboard

`choice_labels_for_values` does not work with mc_multiple items

Open ulyngs opened this issue 2 years ago • 1 comments

Hi Ruben,

it seems that choice_labels_for_values does not work with mc_multiple items for responses where multiple choices have been checked by the respondent (i.e., the data might say "1, 2").

Example: I download some survey data with formr::formr_results.

One of the columns, motivation, has these five first elements:

survey %>% 
  head() %>% 
  pull(motivation)
image

where the response options are

image

So in this case, the 1st and 5th responses should be "productivity, mental health". However, the choice_labels_for_values function instead incorrectly replaces the instances where a participant checked multiple options with NAs:

choice_labels_for_values(survey %>% head(), "motivation")
image

ulyngs avatar Aug 24 '21 15:08 ulyngs

If it's useful, here's the functions I just wrote myself to solve it:

# this helper function takes the name of a column, the column data, and a tibble with the response options for the survey
label_multi_column <- function(some_column_name, some_column_data, choices_for_df){
  label_key <- choices_for_df %>% 
    filter(name == some_column_name) %>% 
    pull(value) %>% 
    unlist()
  
  tibble_replaced <- tibble(to_replace = some_column_data) %>% 
    separate(to_replace, sep = ",", names(label_key), extra = "merge", fill = "right") %>% 
    mutate(across(everything(), str_trim),
           across(everything(), ~recode(., !!!label_key)))
  
  tibble_replaced %>% 
    unite(to_replace, sep = "; ", na.rm = TRUE) %>% 
    pull(to_replace)
}

# this function takes an entire survey downloaded with formr::formr_results and uses the helper function to return the labelled version
replace_with_labels <- function(some_survey){
  survey_items <- formr::items(some_survey)
  
  item_types <- map_chr(survey_items, "type") %>% enframe()
  choices <- map(survey_items, "choices") %>% enframe()

  multiple_response_items <- item_types %>% filter(value == "mc_multiple") %>% pull(name)
  checkbox_items <- item_types %>% filter(value == "check_button") %>% pull(name)

  some_survey %>% 
    mutate(across(all_of(multiple_response_items), ~label_multi_column(cur_column(), ., choices))) %>% 
    mutate(across(all_of(checkbox_items), as.character),
           across(all_of(checkbox_items), ~if_else(. == "1", "checked", "empty"))) %>% 
    mutate(across(where(is.labelled), ~choice_labels_for_values(some_survey, cur_column())))
}

Here, you'd download some survey with formr::formr_results, then call replace_with_labels to get the labelled version:

library(tidyverse)
library(formr)
library(haven) # to use `is.labelled`

formr_connect(keyring = "some-formr-login")

some_survey <- formr_results("some-survey-id")
some_survey_labelled <- replace_with_labels(some_survey)

Note the order of processing in replace_with_labels:

  • first I use my label_multi_column function to label the mc_multiple items
  • afterwards I handle the checkbox items - these are dropped by formr::choice_labels_for_values?
  • finally, I label any remaining labelled columns with formr::choice_labels_for_values

Hope this is helpful!

ulyngs avatar Aug 26 '21 07:08 ulyngs