Gaurav Bansal
Gaurav Bansal

Reputation: 5660

Use checkboxGroupInput to subset df and create ggplot2 in R Shiny

I have some data as shown in the sample df below. There are data for 3 US states (CA, TX, NY) plus the Total, and for each of these there is an actual act, forecast fct, and predicted pred value.

I want to create a Shiny app in which the user can select which states to observe on the plot. To do this I'm using checkboxGroupInput. I have a reactive function named DF in the server portion of my code that subsets df based on user selected states. I then have a reactive function named gl that creates all the geom_line() statements I need to create a ggplot. The reason I'm doing this is because I want to keep the color the same for each state and use linetype to distinguish actual, forecast, or predicted for them.

Lastly, I try to create the plot, but this is where the problem begins. I get no error message, but no plot displays when I run the app. Is there a way to fix this, or a better way to accomplish what I want? Below is the code I have and a plot of what I would like to show if the user had selected all states and Total.

library(shiny)
library(ggplot2)
library(scales)
library(lubridate)

df <- data.frame(Date=seq.Date(as.Date('2017-01-01'), as.Date('2017-05-01'), by='month'),
        CAact=rnorm(5, 10, 2), TXact=rnorm(5, 10, 2), NYact=rnorm(5, 10, 2),Totalact=rnorm(5, 30, 2), 
        CAfct=rnorm(5, 10, 2), TXfct=rnorm(5, 10, 2), NYfct=rnorm(5, 10, 2), Totalfct=rnorm(5, 30, 2),
        CApred=rnorm(5, 10, 2), TXpred=rnorm(5, 10, 2), NYpred=rnorm(5, 10, 2), Totalpred=rnorm(5, 30, 2)
      )

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      checkboxGroupInput('states', 'Select Regions', 
        choices=c('CA','TX','NY','Total'),
        selected=c('CA','TX','NY','Total')
      )
    ),
    mainPanel(
      plotOutput('portfolio')
    )
  )
)

server <- function(input, output){

  #Function to subset df based on user selected states 
  DF <- reactive({
    df <- df[,c('Date', names(df)[grep(paste(input$states, collapse='|'), names(df))])]
    return(df)
  })

  #Generate all the 'geom_line' statements to create ggplot
  gl <- reactive({
    gl <- character()
    lt <- 1
    for(i in 2:length(DF())){
      col <- substr(names(DF())[i], 1, 2)
      if(grepl('Total', names(DF())[i])){
        col <- 'Total'
      }
      if(grepl('fct', names(DF())[i])){
        lt <- 5
      } else if(grepl('pred', names(DF())[i])){
        lt <- 4
      }
      line <- paste0("geom_line(aes(y=", names(DF())[i], ", color='", col, "'), linetype=", lt, ", size=1.25) + ")
      gl <- paste0(gl, line)
    }
  })

  #Create ggplot (not working)
  output$portfolio <- renderPlot({
    paste0("ggplot(data=DF(), aes(Date)) + ", gl(), "labs(x='', y='Balances ($B)')")
  })

}

shinyApp(ui, server)

enter image description here

Upvotes: 0

Views: 470

Answers (1)

Balter
Balter

Reputation: 1095

The error is occurring because of

paste0("ggplot(data=TP, aes(Date)) + ", gl, "labs(x='', y='Balances ($B)')")

You need to refer to gl as gl() since it is a reactive object. After fixing this, there is another error in

DF <- reactive({
    df <- df[,c('Date', names(df)[grep(paste(input$states, collapse='|'), names(df))])]
    return(tpreg)
  }) 

As there is no tpreg object in that function. Changed it to return(df).

Then nothing displays in the plot. I wanted to help fix the rest but I've never seen anyone paste() together a plot so I'm not sure that works...

UPDATE:

Ok.

library(shiny)
library(ggplot2)
library(scales)
library(lubridate)
library(tidyr)

df <- data.frame(Date=seq.Date(as.Date('2017-01-01'), as.Date('2017-05-01'), by='month'),
                 CAact=rnorm(5, 10, 2), TXact=rnorm(5, 10, 2), NYact=rnorm(5, 10, 2),Totalact=rnorm(5, 30, 2), 
                 CAfct=rnorm(5, 10, 2), TXfct=rnorm(5, 10, 2), NYfct=rnorm(5, 10, 2), Totalfct=rnorm(5, 30, 2),
                 CApred=rnorm(5, 10, 2), TXpred=rnorm(5, 10, 2), NYpred=rnorm(5, 10, 2), Totalpred=rnorm(5, 30, 2)
)


df <- gather(df, Variable, Value, -Date)
df$State <- gsub('act|fct|pred', '', df$Variable)
df$Variable <- gsub('CA|NY|TX|Total', '', df$Variable)
df$State <- factor(df$State, levels = c('CA','NY','TX','Total'))

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      checkboxGroupInput('states', 'Select Regions', 
                         choices=c('CA','TX','NY','Total'),
                         selected=c('CA','TX','NY','Total')
      )
    ),
    mainPanel(
      plotOutput('portfolio')
    )
  )
)

server <- function(input, output){

  #Function to subset df based on user selected states 


  color.groups <- c(CA = 'green', TX = 'blue', NY = 'red', Total = 'black')
  line.types <- c(pred = 1, act = 4, fct = 5)

  #Generate all the 'geom_line' statements to create ggplot


  #Create ggplot (not working)
  output$portfolio <- renderPlot({
    sub <- subset(df, subset = State %in% input$states)
    ggplot(sub, aes(x = Date, y = Value, col = State))+
      geom_line(aes(linetype = Variable))+
      scale_color_manual(values = color.groups)+
      scale_linetype_manual(values = line.types)
  })



}

shinyApp(ui, server)

Upvotes: 1

Related Questions