Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/enhance survey questions #326

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

essentialols
Copy link

I think it would be really useful to be able to see the question block and the response options when getting the questions. With this change, the survey_questions function displays the name of the question block and a concatenated version of the response options. The concatenation isn't ideal but I couldn't think of a better way to keep the output tidy.

@essentialols
Copy link
Author

I realize I based this pull request on a much older version. Feel free to ignore any changes that are in conflict with your more recent release.

@juliasilge
Copy link
Collaborator

Thank you for this PR @essentialols! 🙌

FYI we know the metadata situation in this R package isn't ideal right now; we have some discussion on this in #267 as well as all the issues and PRs linked in there, and plan to really revamp the functions like survey_questions() and metadata().

@jmobrien what do you think about making a change like this now, vs. working toward our larger move from v2 to v3 for metadata in general?

Speaking of which, have you tried using metadata() instead for your use case? It shows blocks and choiceText and such:

library(qualtRics)
metadata("SV_3gbwq8aJgqPwQDP")
#> $metadata
#>             surveyID         name            ownerId organizationId isActive
#> 1 SV_3gbwq8aJgqPwQDP Beskar Armor UR_8wfG5qsMxuh0Jrn       conjoint     TRUE
#>           creationDate     lastModifiedDate expiration_startdate
#> 1 2020-02-20T00:35:40Z 2023-07-20T20:39:20Z                   NA
#>   expiration_endDate
#> 1                 NA
#> 
#> $questions
#> $questions$QID63
#> $questions$QID63$questionType
#> $questions$QID63$questionType$type
#> [1] "MC"
#> 
#> $questions$QID63$questionType$selector
#> [1] "SAVR"
#> 
#> $questions$QID63$questionType$subSelector
#> [1] "TX"
#> 
#> 
#> $questions$QID63$questionText
#> [1] "How often do you typically use your beskar armor?"
#> 
#> $questions$QID63$questionLabel
#> NULL
#> 
#> $questions$QID63$validation
#> $questions$QID63$validation$doesForceResponse
#> [1] TRUE
#> 
#> 
#> $questions$QID63$questionName
#> [1] "Q63"
#> 
#> $questions$QID63$choices
#> $questions$QID63$choices$`1`
#> $questions$QID63$choices$`1`$recode
#> [1] "1"
#> 
#> $questions$QID63$choices$`1`$description
#> [1] "<span style=\"color:#8e44ad;\">Daily</span>"
#> 
#> $questions$QID63$choices$`1`$choiceText
#> [1] "<span style=\"color:#8e44ad;\">Daily</span>"
#> 
#> $questions$QID63$choices$`1`$imageDescription
#> NULL
#> 
#> $questions$QID63$choices$`1`$variableName
#> NULL
#> 
#> $questions$QID63$choices$`1`$analyze
#> [1] TRUE
#> 
#> 
#> $questions$QID63$choices$`2`
#> $questions$QID63$choices$`2`$recode
#> [1] "2"
#> 
#> $questions$QID63$choices$`2`$description
#> [1] "Weekly"
#> 
#> $questions$QID63$choices$`2`$choiceText
#> [1] "Weekly"
#> 
#> $questions$QID63$choices$`2`$imageDescription
#> NULL
#> 
#> $questions$QID63$choices$`2`$variableName
#> NULL
#> 
#> $questions$QID63$choices$`2`$analyze
#> [1] TRUE
#> 
#> 
#> $questions$QID63$choices$`3`
#> $questions$QID63$choices$`3`$recode
#> [1] "3"
#> 
#> $questions$QID63$choices$`3`$description
#> [1] "Once a <span style=\"background-color:#9b59b6;\">month</span>"
#> 
#> $questions$QID63$choices$`3`$choiceText
#> [1] "Once a <span style=\"background-color:#9b59b6;\">month</span>"
#> 
#> $questions$QID63$choices$`3`$imageDescription
#> NULL
#> 
#> $questions$QID63$choices$`3`$variableName
#> NULL
#> 
#> $questions$QID63$choices$`3`$analyze
#> [1] TRUE
#> 
#> 
#> $questions$QID63$choices$`4`
#> $questions$QID63$choices$`4`$recode
#> [1] "4"
#> 
#> $questions$QID63$choices$`4`$description
#> [1] "<a href=\"https://www.instagram.com/p/B5qn5ath0ij/?hl=en\">Less often</a>"
#> 
#> $questions$QID63$choices$`4`$choiceText
#> [1] "<a href=\"https://www.instagram.com/p/B5qn5ath0ij/?hl=en\">Less often</a>"
#> 
#> $questions$QID63$choices$`4`$imageDescription
#> NULL
#> 
#> $questions$QID63$choices$`4`$variableName
#> NULL
#> 
#> $questions$QID63$choices$`4`$analyze
#> [1] TRUE
#> 
#> 
#> $questions$QID63$choices$`5`
#> $questions$QID63$choices$`5`$recode
#> [1] "5"
#> 
#> $questions$QID63$choices$`5`$description
#> [1] "Do not use"
#> 
#> $questions$QID63$choices$`5`$choiceText
#> [1] "Do not use"
#> 
#> $questions$QID63$choices$`5`$imageDescription
#> NULL
#> 
#> $questions$QID63$choices$`5`$variableName
#> NULL
#> 
#> $questions$QID63$choices$`5`$analyze
#> [1] TRUE
#> 
#> 
#> 
#> 
#> $questions$QID16
#> $questions$QID16$questionType
#> $questions$QID16$questionType$type
#> [1] "MC"
#> 
#> $questions$QID16$questionType$selector
#> [1] "SAVR"
#> 
#> $questions$QID16$questionType$subSelector
#> [1] "TX"
#> 
#> 
#> $questions$QID16$questionText
#> [1] "Overall, how satisfied are you with your beskar armor?"
#> 
#> $questions$QID16$questionLabel
#> NULL
#> 
#> $questions$QID16$validation
#> $questions$QID16$validation$doesForceResponse
#> [1] TRUE
#> 
#> 
#> $questions$QID16$questionName
#> [1] "Q16"
#> 
#> $questions$QID16$choices
#> $questions$QID16$choices$`5`
#> $questions$QID16$choices$`5`$recode
#> [1] "5"
#> 
#> $questions$QID16$choices$`5`$description
#> [1] "<strong>Extremely</strong> satisfied"
#> 
#> $questions$QID16$choices$`5`$choiceText
#> [1] "<strong>Extremely</strong> satisfied"
#> 
#> $questions$QID16$choices$`5`$imageDescription
#> NULL
#> 
#> $questions$QID16$choices$`5`$variableName
#> NULL
#> 
#> $questions$QID16$choices$`5`$analyze
#> [1] TRUE
#> 
#> 
#> $questions$QID16$choices$`4`
#> $questions$QID16$choices$`4`$recode
#> [1] "4"
#> 
#> $questions$QID16$choices$`4`$description
#> [1] "<a href=\"https://giphy.com/explore/baby-yoda\">Somewhat satisfied</a>"
#> 
#> $questions$QID16$choices$`4`$choiceText
#> [1] "<a href=\"https://giphy.com/explore/baby-yoda\">Somewhat satisfied</a>"
#> 
#> $questions$QID16$choices$`4`$imageDescription
#> NULL
#> 
#> $questions$QID16$choices$`4`$variableName
#> NULL
#> 
#> $questions$QID16$choices$`4`$analyze
#> [1] TRUE
#> 
#> 
#> $questions$QID16$choices$`3`
#> $questions$QID16$choices$`3`$recode
#> [1] "3"
#> 
#> $questions$QID16$choices$`3`$description
#> [1] "<span style=\"background-color:#e74c3c;\">Neither</span> <span style=\"background-color:#e67e22;\">satisfied</span> <span style=\"background-color:#f1c40f;\">nor</span> <span style=\"background-color:#27ae60;\">dissatisfied</span>"
#> 
#> $questions$QID16$choices$`3`$choiceText
#> [1] "<span style=\"background-color:#e74c3c;\">Neither</span> <span style=\"background-color:#e67e22;\">satisfied</span> <span style=\"background-color:#f1c40f;\">nor</span> <span style=\"background-color:#27ae60;\">dissatisfied</span>"
#> 
#> $questions$QID16$choices$`3`$imageDescription
#> NULL
#> 
#> $questions$QID16$choices$`3`$variableName
#> NULL
#> 
#> $questions$QID16$choices$`3`$analyze
#> [1] TRUE
#> 
#> 
#> $questions$QID16$choices$`2`
#> $questions$QID16$choices$`2`$recode
#> [1] "2"
#> 
#> $questions$QID16$choices$`2`$description
#> [1] "<a href=\"https://www.gq.com/story/werner-herzog-baby-yoda\">Somewhat dissatisfied</a>"
#> 
#> $questions$QID16$choices$`2`$choiceText
#> [1] "<a href=\"https://www.gq.com/story/werner-herzog-baby-yoda\">Somewhat dissatisfied</a>"
#> 
#> $questions$QID16$choices$`2`$imageDescription
#> NULL
#> 
#> $questions$QID16$choices$`2`$variableName
#> NULL
#> 
#> $questions$QID16$choices$`2`$analyze
#> [1] TRUE
#> 
#> 
#> $questions$QID16$choices$`1`
#> $questions$QID16$choices$`1`$recode
#> [1] "1"
#> 
#> $questions$QID16$choices$`1`$description
#> [1] "<em>Extremely</em> dissatisfied"
#> 
#> $questions$QID16$choices$`1`$choiceText
#> [1] "<em>Extremely</em> dissatisfied"
#> 
#> $questions$QID16$choices$`1`$imageDescription
#> NULL
#> 
#> $questions$QID16$choices$`1`$variableName
#> NULL
#> 
#> $questions$QID16$choices$`1`$analyze
#> [1] TRUE
#> 
#> 
#> 
#> 
#> $questions$QID17
#> $questions$QID17$questionType
#> $questions$QID17$questionType$type
#> [1] "MC"
#> 
#> $questions$QID17$questionType$selector
#> [1] "SAHR"
#> 
#> $questions$QID17$questionType$subSelector
#> [1] "TX"
#> 
#> 
#> $questions$QID17$questionText
#> [1] "Have you ever contacted customer service about your beskar armor?"
#> 
#> $questions$QID17$questionLabel
#> NULL
#> 
#> $questions$QID17$validation
#> $questions$QID17$validation$doesForceResponse
#> [1] TRUE
#> 
#> 
#> $questions$QID17$questionName
#> [1] "Q17"
#> 
#> $questions$QID17$choices
#> $questions$QID17$choices$`1`
#> $questions$QID17$choices$`1`$recode
#> [1] "1"
#> 
#> $questions$QID17$choices$`1`$description
#> [1] "Yes"
#> 
#> $questions$QID17$choices$`1`$choiceText
#> [1] "Yes"
#> 
#> $questions$QID17$choices$`1`$imageDescription
#> NULL
#> 
#> $questions$QID17$choices$`1`$variableName
#> NULL
#> 
#> $questions$QID17$choices$`1`$analyze
#> [1] TRUE
#> 
#> 
#> $questions$QID17$choices$`2`
#> $questions$QID17$choices$`2`$recode
#> [1] "2"
#> 
#> $questions$QID17$choices$`2`$description
#> [1] "No"
#> 
#> $questions$QID17$choices$`2`$choiceText
#> [1] "No"
#> 
#> $questions$QID17$choices$`2`$imageDescription
#> NULL
#> 
#> $questions$QID17$choices$`2`$variableName
#> NULL
#> 
#> $questions$QID17$choices$`2`$analyze
#> [1] TRUE
#> 
#> 
#> 
#> 
#> $questions$QID18
#> $questions$QID18$questionType
#> $questions$QID18$questionType$type
#> [1] "MC"
#> 
#> $questions$QID18$questionType$selector
#> [1] "SAVR"
#> 
#> $questions$QID18$questionType$subSelector
#> [1] "TX"
#> 
#> 
#> $questions$QID18$questionText
#> [1] "Have all problems been resolved to your complete satisfaction?"
#> 
#> $questions$QID18$questionLabel
#> NULL
#> 
#> $questions$QID18$validation
#> $questions$QID18$validation$doesForceResponse
#> [1] FALSE
#> 
#> 
#> $questions$QID18$questionName
#> [1] "Q18"
#> 
#> $questions$QID18$choices
#> $questions$QID18$choices$`1`
#> $questions$QID18$choices$`1`$recode
#> [1] "1"
#> 
#> $questions$QID18$choices$`1`$description
#> [1] "Yes, by the tribe or its representatives \n<video class=\"qmedia\" controls=\"true\" height=\"268\" preload=\"auto\" width=\"268\"><source src=\"https://i.imgur.com/QlAme0q.mp4\" type=\"video/mp4\" /><embed align=\"middle\" autoplay=\"false\" bgcolor=\"white\" class=\"qmedia\" controller=\"true\" height=\"268\" pluginspage=\"http://www.apple.com/quicktime/download/\" src=\"https://i.imgur.com/QlAme0q.mp4\" type=\"video/quicktime\" width=\"268\" /></video>\n"
#> 
#> $questions$QID18$choices$`1`$choiceText
#> [1] "Yes, by the tribe or its representatives \n<video class=\"qmedia\" controls=\"true\" height=\"268\" preload=\"auto\" width=\"268\"><source src=\"https://i.imgur.com/QlAme0q.mp4\" type=\"video/mp4\" /><embed align=\"middle\" autoplay=\"false\" bgcolor=\"white\" class=\"qmedia\" controller=\"true\" height=\"268\" pluginspage=\"http://www.apple.com/quicktime/download/\" src=\"https://i.imgur.com/QlAme0q.mp4\" type=\"video/quicktime\" width=\"268\" /></video>\n"
#> 
#> $questions$QID18$choices$`1`$imageDescription
#> NULL
#> 
#> $questions$QID18$choices$`1`$variableName
#> NULL
#> 
#> $questions$QID18$choices$`1`$analyze
#> [1] TRUE
#> 
#> 
#> $questions$QID18$choices$`2`
#> $questions$QID18$choices$`2`$recode
#> [1] "2"
#> 
#> $questions$QID18$choices$`2`$description
#> [1] "Yes, by me or someone outside the tribe \n<video class=\"qmedia\" controls=\"true\" height=\"268\" preload=\"auto\" width=\"268\"><source src=\"https://i.imgur.com/5sRVO4d.mp4\" type=\"video/mp4\" /><embed align=\"middle\" autoplay=\"false\" bgcolor=\"white\" class=\"qmedia\" controller=\"true\" height=\"268\" pluginspage=\"http://www.apple.com/quicktime/download/\" src=\"https://i.imgur.com/5sRVO4d.mp4\" type=\"video/quicktime\" width=\"268\" /></video>\n"
#> 
#> $questions$QID18$choices$`2`$choiceText
#> [1] "Yes, by me or someone outside the tribe \n<video class=\"qmedia\" controls=\"true\" height=\"268\" preload=\"auto\" width=\"268\"><source src=\"https://i.imgur.com/5sRVO4d.mp4\" type=\"video/mp4\" /><embed align=\"middle\" autoplay=\"false\" bgcolor=\"white\" class=\"qmedia\" controller=\"true\" height=\"268\" pluginspage=\"http://www.apple.com/quicktime/download/\" src=\"https://i.imgur.com/5sRVO4d.mp4\" type=\"video/quicktime\" width=\"268\" /></video>\n"
#> 
#> $questions$QID18$choices$`2`$imageDescription
#> NULL
#> 
#> $questions$QID18$choices$`2`$variableName
#> NULL
#> 
#> $questions$QID18$choices$`2`$analyze
#> [1] TRUE
#> 
#> 
#> $questions$QID18$choices$`3`
#> $questions$QID18$choices$`3`$recode
#> [1] "3"
#> 
#> $questions$QID18$choices$`3`$description
#> [1] "No, the problem was not resolved \n<video class=\"qmedia\" controls=\"true\" height=\"168\" preload=\"auto\" width=\"268\"><source src=\"https://i.imgur.com/i40m72o.mp4\" type=\"video/mp4\" /><embed align=\"middle\" autoplay=\"false\" bgcolor=\"white\" class=\"qmedia\" controller=\"true\" height=\"168\" pluginspage=\"http://www.apple.com/quicktime/download/\" src=\"https://i.imgur.com/i40m72o.mp4\" type=\"video/quicktime\" width=\"268\" /></video>\n"
#> 
#> $questions$QID18$choices$`3`$choiceText
#> [1] "No, the problem was not resolved \n<video class=\"qmedia\" controls=\"true\" height=\"168\" preload=\"auto\" width=\"268\"><source src=\"https://i.imgur.com/i40m72o.mp4\" type=\"video/mp4\" /><embed align=\"middle\" autoplay=\"false\" bgcolor=\"white\" class=\"qmedia\" controller=\"true\" height=\"168\" pluginspage=\"http://www.apple.com/quicktime/download/\" src=\"https://i.imgur.com/i40m72o.mp4\" type=\"video/quicktime\" width=\"268\" /></video>\n"
#> 
#> $questions$QID18$choices$`3`$imageDescription
#> NULL
#> 
#> $questions$QID18$choices$`3`$variableName
#> NULL
#> 
#> $questions$QID18$choices$`3`$analyze
#> [1] TRUE
#> 
#> 
#> 
#> 
#> $questions$QID19
#> $questions$QID19$questionType
#> $questions$QID19$questionType$type
#> [1] "TE"
#> 
#> $questions$QID19$questionType$selector
#> [1] "ESTB"
#> 
#> $questions$QID19$questionType$subSelector
#> NULL
#> 
#> 
#> $questions$QID19$questionText
#> [1] "Why not?"
#> 
#> $questions$QID19$questionLabel
#> NULL
#> 
#> $questions$QID19$validation
#> $questions$QID19$validation$doesForceResponse
#> [1] FALSE
#> 
#> 
#> $questions$QID19$questionName
#> [1] "Q19"
#> 
#> 
#> $questions$QID22
#> $questions$QID22$questionType
#> $questions$QID22$questionType$type
#> [1] "TE"
#> 
#> $questions$QID22$questionType$selector
#> [1] "ESTB"
#> 
#> $questions$QID22$questionType$subSelector
#> NULL
#> 
#> 
#> $questions$QID22$questionText
#> [1] "If you would like to share any additional comments or experiences about your beskar armor, please enter them below."
#> 
#> $questions$QID22$questionLabel
#> NULL
#> 
#> $questions$QID22$validation
#> $questions$QID22$validation$doesForceResponse
#> [1] FALSE
#> 
#> 
#> $questions$QID22$questionName
#> [1] "Q22"
#> 
#> 
#> 
#> $responsecounts
#> data frame with 0 columns and 0 rows

Created on 2023-09-05 with reprex v2.0.2

@essentialols
Copy link
Author

Thanks for responding and for suggesting to look into the metadata() function. I'll take a closer look. However, I think there would be great benefit to have this function return a tibble, even if the tibble would be difficult to rectangle with response options possibly differing by question. While I simply concatenated the response options (the goal being to have a concise overview of the response options rather than to continue to work with them), they could also be made easily readable in other ways.

@jmobrien
Copy link
Collaborator

jmobrien commented Sep 7, 2023

@essentialols I'm not sure, but the question about metadata() might have been directed at me - @juliasilge and I have a long ongoing conversation about qualtRics's support of metadata + metadata processing. (if it was, @juliasilge, I'll just say that I'm aware of what's available in metadata(), but the details on it vs. fetch_description() are kind of complex and out of scope for this thread.)

Meanwhile, @essentialols, the survey_questions() function that you're expanding on here is already just a variant of metadata(), with the former adding some filtering/reshaping like you describe. I think we all agree on aiming for user-friendly output like tibbles/dataframes, so I think your approach of expanding on survey_questions() in general makes sense and is fine.

That said, my main concern is that this might not actually work as a general-purpose feature addition--at least not yet, and perhaps not without a lot more effort. Qualtrics has some rather non-intuitive ways it internally represents things in its metadata--for example, a Matrix-type question doesn't use the same structure to represent response options that a standard multiple-choice question uses. So the code so far might not work for that situation.

So, actually implementing this (whether on top of metadata() or fetch_description() either one) might require a good bit of more sophisticated work to adapt to different situations. People definitely want that, but it kind of depends on how much someone wants to really dive in.

So, this looks good as a start and I'm excited you're taking a stab at it, but having dealt with something similar I just wanted to make sure you had an honest take up front in case you decide you really want to tackle this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants