Making a Multi-Paged shinysurvey
By Jonathan Trattner in R Shiny Packages shinysurveys
June 27, 2021
Introduction
As of shinysurveys version 0.2.0, users can optionally split a survey over multiple pages. In this brief blog post, I’ll illustrate an example of this with the built-in data frame of questions from a recent study conducted by the D’Agostino McGowan Data Science Lab.
In addition to shinysurveys
, I will use the packages dplyr
and tidyr
in this example for easily manipulating the data frame.
library(shinysurveys)
library(dplyr)
library(tidyr)
One Page Survey
teaching_r_questions
is a data frame with eleven questions that follow the format of a shiny survey. The first ten rows look like this:1
## # A tibble: 54 x 7
## question option input_type input_id dependence dependence_value required
## <chr> <chr> <chr> <chr> <chr> <chr> <lgl>
## 1 What's you… 25 numeric age <NA> <NA> TRUE
## 2 Which best… Female mc gender <NA> <NA> TRUE
## 3 Which best… Male mc gender <NA> <NA> TRUE
## 4 Which best… Prefer … mc gender <NA> <NA> TRUE
## 5 Which best… Prefer … mc gender <NA> <NA> TRUE
## 6 Which best… <NA> text self_de… gender Prefer to self … FALSE
## 7 What is th… Did not… select educati… <NA> <NA> FALSE
## 8 What is th… Some hi… select educati… <NA> <NA> FALSE
## 9 What is th… High sc… select educati… <NA> <NA> FALSE
## 10 What is th… Some co… select educati… <NA> <NA> FALSE
## # … with 44 more rows
The function demo_survey()
allows you to see what a shiny survey may look like using these questions. Internally, the following shiny app is defined:
library(shiny)
library(shinysurveys)
ui <- fluidPage(
surveyOutput(df = teaching_r_questions,
survey_title = "A survey title",
survey_description = "A description that is longer than the title.",
theme = "#63B8FF"
)
)
server <- function(input, output, session) {
renderSurvey()
}
shinyApp(ui, server)
Multiple Paged Survey
Having run the single-paged example, I think the survey may be easier to complete if the questions are displayed over multiple pages. I’ll organize it as follows:
First Page: Questions about age, gender, and education level.
Second Page: Questions about language and reading.
Third Page: Questions about programming and data analysis.
To create a shiny survey that spans multiple pages, the data frame of questions must be modified to include a ‘page’ column that specifies the location for each question.
In our example, the survey has questions with dependencies (conditionally shown questions), so I want to make sure all the parent and children questions are on the same page. To do this, I’ll group the data frame by each question and nest the other columns for a simpler manipulation:
nested_questions <- teaching_r_questions %>%
group_by(question) %>%
nest() %>%
ungroup()
nested_questions
## # A tibble: 11 x 2
## question data
## <chr> <list>
## 1 What's your age? <tibble [1 × …
## 2 Which best describes your gender? <tibble [5 × …
## 3 What is the highest level of education you have attained? <tibble [6 × …
## 4 What was your first language? <tibble [15 ×…
## 5 In what language do you read most often? <tibble [15 ×…
## 6 Have you ever learned to program in R? <tibble [2 × …
## 7 If yes, how many years have you been using R? <tibble [1 × …
## 8 Have you ever learned a programming language (other than R)? <tibble [2 × …
## 9 If yes, which language(s) and how many years have you been us… <tibble [1 × …
## 10 Have you ever completed a data analysis? <tibble [2 × …
## 11 If yes, approximately how many data analyses have you complet… <tibble [4 × …
We can see that the first three rows should be on page 1, the fourth and fifth rows on page 2, and the remaining six rows on page 3. One easy way to add a column is with dplyr::mutate()
like such:
multiQuestions <- nested_questions %>%
mutate(page = c(
rep(1, 3),
rep(2, 2),
rep(3, 6))
)
multiQuestions
## # A tibble: 11 x 3
## question data page
## <chr> <list> <dbl>
## 1 What's your age? <tibble [1 ×… 1
## 2 Which best describes your gender? <tibble [5 ×… 1
## 3 What is the highest level of education you have attained? <tibble [6 ×… 1
## 4 What was your first language? <tibble [15 … 2
## 5 In what language do you read most often? <tibble [15 … 2
## 6 Have you ever learned to program in R? <tibble [2 ×… 3
## 7 If yes, how many years have you been using R? <tibble [1 ×… 3
## 8 Have you ever learned a programming language (other than… <tibble [2 ×… 3
## 9 If yes, which language(s) and how many years have you be… <tibble [1 ×… 3
## 10 Have you ever completed a data analysis? <tibble [2 ×… 3
## 11 If yes, approximately how many data analyses have you co… <tibble [4 ×… 3
Our last step is to unnest the questions, i.e. to restructure data frame into the format accepted by shinysurveys:
multiQuestions <- multiQuestions %>%
unnest(cols = data)
And voila! Just like that, we have a data frame to specify a multi-paged shiny survey. To double check we organized it correctly, we can group the data by page and question as follows:
multiQuestions %>%
group_by(page, question) %>%
slice_head() %>%
ungroup() %>%
select(question, page)
## # A tibble: 11 x 2
## question page
## <chr> <dbl>
## 1 What is the highest level of education you have attained? 1
## 2 What's your age? 1
## 3 Which best describes your gender? 1
## 4 In what language do you read most often? 2
## 5 What was your first language? 2
## 6 Have you ever completed a data analysis? 3
## 7 Have you ever learned a programming language (other than R)? 3
## 8 Have you ever learned to program in R? 3
## 9 If yes, approximately how many data analyses have you completed? 3
## 10 If yes, how many years have you been using R? 3
## 11 If yes, which language(s) and how many years have you been using each … 3
Looks good to me! We can use this data frame to create a multi-paged survey as follows:
library(shiny)
library(shinysurveys)
ui <- fluidPage(
surveyOutput(df = multiQuestions,
survey_title = "A survey title",
survey_description = "A description that is longer than the title.",
theme = "#63B8FF"
)
)
server <- function(input, output, session) {
renderSurvey()
}
shinyApp(ui, server)
The above code is packaged within the function demo_survey_multipage()
.
Conclusion
In this post, I briefly illustrated how to convert a single paged shiny survey to a multi-paged one. You can see the examples for yourself with the functions demo_survey()
and demo_survey_multipage()
built into shinysurveys.
For any questions or feedback, please leave a comment below! More of my work can be seen on GitHub. If you want to chat about anything (including neuroscience, #rstats, piano, or my cat), DM me on Twitter. Lastly, if you need help with an #rstats or shiny project, I’m available for consulting – just send me an email!
See this vignette for an overview of each column.↩︎