Skip to content

Commit 651f9c5

Browse files
committed
subq export list uses recoded and carried-forward values
1 parent 1ce3434 commit 651f9c5

File tree

1 file changed

+49
-7
lines changed

1 file changed

+49
-7
lines changed

facebook/qsf-tools/qsf-differ.R

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ suppressPackageStartupMessages({
1515
library(jsonlite)
1616
library(stringr)
1717
library(dplyr)
18+
library(purrr)
1819
library(readr)
1920
source("qsf-utils.R")
2021
})
@@ -63,27 +64,68 @@ get_qsf_file <- function(path,
6364
## Questions
6465
questions <- Filter(function(elem) { elem[["Element"]] == "SQ" }, qsf$SurveyElements)
6566

67+
qids <- questions %>%
68+
map_chr(~ .x$Payload$QuestionID)
69+
6670
qid_item_map <- list()
6771
questions_out <- list()
68-
for (question in questions) {
69-
question <- question$Payload
72+
for (question_raw in questions) {
73+
question_raw <- question_raw$Payload
7074

7175
# Skip items not shown to respondents.
72-
if ( !(question$QuestionID %in% shown_items) ) {
76+
if ( !(question_raw$QuestionID %in% shown_items) ) {
7377
next
7478
}
7579

76-
if (!identical(keep_items, c("all"))) {
77-
question <- question[names(question) %in% c("QuestionID", keep_items)]
80+
question <- question_raw[names(question_raw) %in% c("QuestionID", keep_items)]
81+
82+
recode_values <- question_raw$RecodeValues # If doesn't exist, will be NULL
83+
carryforward_choices <- question_raw$DynamicChoices$Locator # If doesn't exist, will be NULL
84+
85+
if (!is.null(carryforward_choices)) {
86+
# Get choices that are programmed specifically for this question
87+
old_choices <- question$Choices
88+
89+
# Get carried-forward choices
90+
carryforward_choices_qid <- carryforward_choices %>%
91+
str_split(., "/") %>%
92+
map(~ .x[3]) %>% unlist()
93+
carryforward_question <- questions[qids == carryforward_choices_qid][[1]]$Payload
94+
carryforward_choices <- carryforward_question$Choices
95+
96+
# By default, carried forward choices are coded during the carry as
97+
# "x<original code>". They are then recoded as pure numeric codes using
98+
# the `RecodeValues` field. Some carried forward choices do not have
99+
# `RecodeValues` defined and so in that case we don't want to prepend the
100+
# codes with "x".
101+
if (!is.null(recode_values)) {
102+
names(carryforward_choices) <- paste0("x", names(carryforward_choices))
103+
}
104+
# Combine new choices and carried-forward choices
105+
question$Choices <- c(old_choices, carryforward_choices)
78106
}
79107

80-
# Rearrange Answers/Choices elements to be consistent between matrix and
81-
# other items.
82108
if ("QuestionType" %in% names(question)) {
83109
if (question$QuestionType == "Matrix") {
110+
# Rearrange Answers/Choices elements to be consistent between matrix and
111+
# other items.
84112
question$Subquestions <- question$Choices
85113
question$Choices <- question$Answers
86114
question$Answers <- NULL
115+
116+
# Recode subquestion names to match exported data.
117+
# FALSE if not set, otherwise a list
118+
matrix_subquestion_field_names <- question_raw$ChoiceDataExportTags
119+
if (!inherits(matrix_subquestion_field_names, "list")) {
120+
# When subquestion field names are not set, generate incrementing names
121+
names(question$Subquestions) <- paste(
122+
question$DataExportTag,
123+
1:length(question$Subquestions),
124+
sep = "_"
125+
)
126+
} else {
127+
names(question$Subquestions) <- matrix_subquestion_field_names[names(question$Subquestions)] %>% unlist()
128+
}
87129
}
88130
}
89131

0 commit comments

Comments
 (0)