'How to group_by() and summarise() data reactively with shiny?
I am constructing a shiny web app that allows users to get the best of dplyr (data wrangling & manipulation R package) without coding in R.
I would like to group_by() and summarise() using respectively a selectInput that allow choosing a variable among all those available in the "movies" file (http://s3.amazonaws.com/assets.datacamp.com/production/course_4850/datasets/movies.Rdata")
Any body knows how to fix this please?
When using the following server function, I get an empty table ...
shinyServer(function(input, output){
output$table <- DT::renderDataTable({
moviesSummarise <- movies %>%
group_by(inputx) %>%
summarise(Moyenne = mean(input$y))
DT::datatable(data = moviesSummarise)
})
})
Many thanks.
if (interactive()){
load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_4850/datasets/movies.Rdata"))
# Libraries
library(dplyr)
library(shiny)
library(shinydashboard)
library(DT)
ui1 <- shinyUI(
dashboardPage(
dashboardHeader(title = "Data Viewer"),
dashboardSidebar(
selectInput(inputId = "x",
label = "Grouper par :",
choices = c("title_type", "genre", "mpaa_rating",
"studio", "thtr_rel_year"),
selected = "thtr_rel_year"),
selectInput(inputId = "y",
label = "Résumé par :",
choices = c("runtime","imdb_num_votes",
"critics_score", "audience_score"),
selected = "runtime")
),
dashboardBody(
fluidPage(
box(DT::dataTableOutput(outputId = "table"), title="Résumé des données :", height = 300)
)
)
)
)
server1 <- shinyServer(function(input, output){
output$table <- DT::renderDataTable({
moviesSummarise <- movies %>%
group_by(genre) %>%
## It doesn't work when I tried group_by(input$x)
summarise(Moyenne = mean(runtime))
## It doesn't work when I tried summarise(input$y)
DT::datatable(data = moviesSummarise)
})
})
shinyApp(ui = ui1, server = server1)
}
I expect that the summary table will change reactively when I group_by() / summarise() a new variable using the selectInput("x", ...) and selectInput("y", ...)
With the above pasted code, it generates an empty table.
Solution 1:[1]
Two ways to do this: using scoped versions of group_by and summarise (which will pick up the strings) or rlang to unquote the inputs.
Neither group_by nor summarize like strings and rather expect bare names:
> movies %>%
+ group_by("title_type") %>%
+ summarise(Moyenne = mean("runtime"))
# A tibble: 1 x 2
`"title_type"` Moyenne
<chr> <dbl>
1 title_type NA
> movies %>%
+ group_by(title_type) %>%
+ summarise(Moyenne = mean(runtime))
# A tibble: 3 x 2
title_type Moyenne
<fct> <dbl>
1 Documentary NA
2 Feature Film 107.
3 TV Movie 102.
Using the scope versions:
> movies %>%
+ group_by_at("title_type") %>%
+ summarise_at(vars(one_of("runtime")), list(Moyenne = mean))
# A tibble: 3 x 2
title_type Moyenne
<fct> <dbl>
1 Documentary NA
2 Feature Film 107.
3 TV Movie 102.
Or you can use the rlang approach and unqoute the strings:
> movies %>%
+ group_by(!! sym("title_type")) %>%
+ summarise(Moyenne = mean(!!sym("runtime")))
# A tibble: 3 x 2
title_type Moyenne
<fct> <dbl>
1 Documentary NA
2 Feature Film 107.
3 TV Movie 102.
So:
if (interactive()){
load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_4850/datasets/movies.Rdata"))
# Libraries
library(dplyr)
library(shiny)
library(shinydashboard)
library(DT)
ui1 <- shinyUI(
dashboardPage(
dashboardHeader(title = "Data Viewer"),
dashboardSidebar(
selectInput(inputId = "x",
label = "Grouper par :",
choices = c("title_type", "genre", "mpaa_rating",
"studio", "thtr_rel_year"),
selected = "thtr_rel_year"),
selectInput(inputId = "y",
label = "Résumé par :",
choices = c("runtime","imdb_num_votes",
"critics_score", "audience_score"),
selected = "runtime")
),
dashboardBody(
fluidPage(
box(DT::dataTableOutput(outputId = "table"), title="Résumé des données :", height = 300)
)
)
)
)
server1 <- shinyServer(function(input, output){
output$table <- DT::renderDataTable({
moviesSummarise <- movies %>%
group_by(!! sym(input$x)) %>%
summarise(Moyenne = mean(!!sym(input$y)))
DT::datatable(data = moviesSummarise)
})
})
shinyApp(ui = ui1, server = server1)
Solution 2:[2]
Another solution is to use the dplyr data-masking method, namely referring shiny reactive variables in dplyr verbs through .data[[input$id]] in reactive functions. Most dplyr verbs do not accept strings as inputs, data-masking method allows us refer data variables and environment variables (.env[[]]) through character strings. For example:
change group_by(input$x) %>% to group_by (.data[[input$x]]) %>%, and
change %>% summarise(Moyenne = mean(input$y)) to %>% summarise(Moyenne = mean(.data[[input$y]])).
I have checked and your code should all work now.
Solution 3:[3]
Correction of the first server.
shinyServer(function(input, output){
output$table <- DT::renderDataTable({
moviesSummarise <- movies %>%
group_by(input$x) %>%
summarise(Moyenne = mean(input$y))
DT::datatable(data = moviesSummarise)
})
})
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | paqmo |
| Solution 2 | Researchnology |
| Solution 3 | Rodrigo Orellana |
