Home > Back-end >  R Shiny - Create an interactive group_by() and summarise() plot inside a dashboard
R Shiny - Create an interactive group_by() and summarise() plot inside a dashboard

Time:09-20

Brand new to R so wondering if someone can help me understand where I'm going wrong here. Apologies if I've butchered the format or handed you terrible code to work from.

My goal is to get dashboard out containing a plot, whereby I can choose a column from my data and group_by that selected column, then calculate the mean of a different column for each bin in the selected column. Giving me a graph with the column selected across the x-axis and the average calculated up the y. Hopefully the code I've tried so far will shed more light on this:

library(tidyverse)
library(shiny)
library(shinydashboard)

df <- 
 data.frame(Car_Col = c("Red","Blue","Red","Black","white","Black","Black","White","Red","Blue"),
            Car_Type = c("E","G","D","G","G","D","G","D","E","G"),
            Sold = (c(1,0,1,0,0,0,1,1,0,0)))
  

## app.R ##
library(shiny)
library(shinydashboard)

ui <- dashboardPage(
 dashboardHeader(),
 dashboardSidebar(),
 dashboardBody(fluidRow(selectInput(inputId = "x",
                                    label = "Select variable",
                                    choices = c("Car_Col","Car_Type", selected = "Car_Col"))),
               plotOutput("graph1")
   
   
   
 )
)

server <- function(input, output) { 

 output$graph1 <- renderPlot({
   df_summarise <- 
     df %>% 
     group_by(get(input$x)) %>% 
     summarise(Avg_Sold = mean(Sold)) %>% 
     ungroup() >%>
     ggplot(df, mapping = aes(x=get(input$x), y=Avg_Sold, group=1)  geom_point(size=2))  geom_line()
   
 })
 
 
 }

shinyApp(ui, server)


So for instance I want a plot where the user can select if they want to see the average sold across Car_Col, or across Car_Type - obviously wanting them calculated uniquely to the selection.

So for example the mean value of sold cars across colour I'd want Red, Blue, Black and White across the x-axis, with their respective means (so red having 2 sold and 3 cars should be at 0.67, etc)

Currently the error I'm getting is this:

Warning: Error in group_by: Problem adding computed columns.
Caused by error in `mutate()`:
! Problem while computing `..1 = get(input$x)`.
Caused by error in `get()`:
! invalid first argument

...
...

Warning: Error in ggplot: Mapping should be created with `aes()` or `aes_()`.

I believe from what I can find from other similar questions that I'm treating the input$x incorrectly and the error is stemming, as above, from the get(input$x), but whenever I try to do it outside of the plot then it's outside of a reactive environment - and I can't make that work either (though I only tried something like using var = reactive({input$x)} and referencing var() in place of get(input$x) but that didn't work either).

Any help would be appreciated, thank you!

CodePudding user response:

There are several issues with your code. First you placed several closing parentheses in the wrong place. Second, you pipe your data into ggplot but additionally pass df to the data argument. Third, there is a typo in one of the pipes, i.e. you use >%> instead of %>%. Finally group_by(get(input$x)) will not work. Use e.g. group_by(across(input$x)) or group_by(data[[input$x]]) as I do below.

Additionally, while x=get(input$x) works I would still suggest to use x = .data[[input$x]].

library(tidyverse)
library(shiny)
library(shinydashboard)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    fluidRow(selectInput(
      inputId = "x",
      label = "Select variable",
      choices = c("Car_Col", "Car_Type"), selected = "Car_Col"
    )),
    plotOutput("graph1")
  )
)

server <- function(input, output) {
  output$graph1 <- renderPlot({
    df %>%
      group_by(.data[[input$x]]) %>%
      summarise(Avg_Sold = mean(Sold)) %>%
      ungroup() %>%
      ggplot(mapping = aes(x = .data[[input$x]], y = Avg_Sold, group = 1))  
      geom_point(size = 2)  
      geom_line()
  })
}

shinyApp(ui, server)
#> 
#> Listening on http://127.0.0.1:5153

CodePudding user response:

library(tidyverse)
library(shiny)
library(shinydashboard)

df <- 
    data.frame(Car_Col = c("Red","Blue","Red","Black","white","Black","Black","White","Red","Blue"),
               Car_Type = c("E","G","D","G","G","D","G","D","E","G"),
               Sold = (c(1,0,1,0,0,0,1,1,0,0)))


## app.R ##
ui <- dashboardPage(
    dashboardHeader(),
    dashboardSidebar(),
    dashboardBody(fluidRow(selectInput(inputId = "x",
                                       label = "Select variable",
                                       choices = c("Car_Col","Car_Type", selected = "Car_Col"))),
                  plotOutput("graph1")
                  
                  
                  
    )
)

server <- function(input, output) { 
    
    output$graph1 <- renderPlot({
        req(input$x)
        df %>% 
        group_by_at(input$x) %>% 
        summarise(Avg_Sold = mean(Sold)) %>% 
        ungroup() %>% 
        ggplot(mapping = aes_string(x=input$x, y='Avg_Sold', group=1))   
           geom_point(size=2)   
           geom_line()
        
    })
    
    
}

shinyApp(ui, server)

value in input$x is a string, you need to use group_by_at which accepts a character vector. In aes, it needs column name without quotes, so we use the string version aes_string.

enter image description here

  • Related