I apologize in case this questions sounds to basic, but I am trying already for a while and it still doesnt work. (I saw there was a similar question already here but after trying to implement what was suggested there I still recieved an error). So I would be very grateful if somebody could explain to me in more detail what I do wrong with an example of code.

I have the following data set:

year <- c(2000, 2002, 2006, 2000, 2004, 2010, 2010, 2011, 2020, 2006)
prices <- c(100, 200, 300, 120, 240, 400, 430, 490, 700, 650)
colors1 <- c("red", "red", "blue", "green","blue", "red", "blue", "green", "green", "red")
size <- c("s", "m", "l", "xl", "l", "s", "m", "xl", "l","m")
city <- c("NY","LA", "DC","NY","LA", "DC","NY","LA", "DC", "NY")
delivery <- c(3, 7, 3, 10, 20, 5, 10, 2, 12,4)
df <- data.frame(year, prices, colors1,size,city, delivery, stringsAsFactors = FALSE)

df$vatprice<- df$prices * 1.2

This is the structure of my data set. It looks basically like this.

   year prices colors1 size city delivery vatprices
1  2000    100     red    s   NY        3       120
2  2002    200     red    m   LA        7       240
3  2006    300    blue    l   DC        3       360
4  2000    120   green   xl   NY       10       144
5  2004    240    blue    l   LA       20       288
6  2010    400     red    s   DC        5       480
7  2010    430    blue    m   NY       10       516
8  2011    490   green   xl   LA        2       588
9  2020    700   green    l   DC       12       840
10 2006    650     red    m   NY        4       780

Now what I am trying to do I want to create a small shiny App which would show the following:

on the x-axis a range of years (as you can see my years are descrete but I hope I can still set them as a range)

on y axis: either price or vatprice

and all this data should be categorized either by color, size or city.

ui <- basicPage(
  sidebarPanel(
    sliderInput("range", "Year:",min = 1990, max = 2040, value = c(2000,2020)),textOutput("SliderText"),
    selectInput("yaxis", "Y Variable", names(df[,c(2,7)]), selected = names(df)[[2]]),
    radioButtons(inputId = "cat", label = "Categorized by:", names(df[,c(3:5)]))
  ), # closing of the sidebar panel
  plotOutput("scatter")

)


# server 

server <- shinyServer(function(input, output){

  my_range <- reactive({
    cbind(input$range[1],input$range[2])
  })
  output$SliderText <- renderText({my_range()})

  output$scatter <- renderPlot({
    ggplot(df, aes(df$year, df$prices)) + 
   geom_point(aes(color = factor(df$size))) + labs(title = "Overview",
                  color = "Legend") + xlab("Year") + ylab("Price") + theme_minimal()

  })})


shinyApp(ui = ui, server = server)

So when I run the programm I get basically already my entire UI and the graph itself. But I have to conenct somehow my df data set with the server in order to make my shiny app interactive.

So my question is: Do I have to create a reactive variable for each of those columns? Or should I just create one reactive data set? Can somebody show me the logic behind, cause I still feel lost.

I tryed to do it like here: How do I connect my inputs to my graph outputs but still got an error - so I removed it and kept only my basic UI and server function, since they dont show any errors.

2 Answers

0
A. Suliman On Best Solutions

First, we need to get a final df in terms of year range and column names based on what the user has entered. Then we need to pass these variables to ggplot using !!sym since they will be in string form i.e prices will be "prices" not prices.

library(dplyr)
library(ggplot2)
server <- shinyServer(function(input, output){

  my_range <- reactive({
    cbind(input$range[1],input$range[2])
  })

  df_final <- reactive({
    filter(df, between(year,input$range[1],input$range[2])) %>% 
    select(year,input$yaxis,input$cat) 
  })

  output$SliderText <- renderText({my_range()})

  #Check if filter and select work correctly and as we wanted
  observe(print(str(df_final()))) 

  output$scatter <- renderPlot({
    ggplot(df_final(), aes(year, !!sym(input$yaxis))) + 
      geom_point(aes(color = factor(!!sym(input$cat)))) + labs(title = "Overview",
                                                      color = "Legend") + xlab("Year") + ylab("Price") + theme_minimal()

  })})


shinyApp(ui = ui, server = server)
0
Community On

I propose another answer, I made several change, first I inspired myself from the basic tutorial :

https://shiny.rstudio.com/tutorial/written-tutorial/lesson4/

Secondly I use aes_string as in :

Best way to convert character strings in to function arguments in R/ggplot2?

It seems to me more natural for what I did. Secondly I made the selection inside the server I don't know if it is efficient but I think that it is clear. Secondly your cbind inside data.frame call is a bad idea beacause you force every variable to be the same type and it is not what you want.

year <- c(2000, 2002, 2006, 2000, 2004, 2010, 2010, 2011, 2020, 2006)
Price <- c(100, 200, 300, 120, 240, 400, 430, 490, 700, 650)
colors1 <- c("red", "red", "blue", "green","blue", "red", "blue", "green", "green", "red")
size <- c("s", "m", "l", "xl", "l", "s", "m", "xl", "l","m")
city <- c("NY","LA", "DC","NY","LA", "DC","NY","LA", "DC", "NY")
delivery <- c(3, 7, 3, 10, 20, 5, 10, 2, 12,4)
df <- data.frame(year,
                 Price,
                 colors1,
                 size, city,
                 delivery)

df$Vatprice <- df$Price * 1.2

str(df)

library(shiny)
library(ggplot2)

ui <- fluidPage(
  sidebarPanel(
    sliderInput("range",
                "Year:", min = 1990,
                max = 2040, value = c(2000, 2020)),
    textOutput("SliderText"),
    selectInput("yaxis",
                "Y Variable",
                names(df[,c(2,7)]),
                selected = names(df)[[2]]),
    radioButtons(inputId = "cat",
                 label = "Categorized by:",
                 names(df[,3:5]))
  ),
  mainPanel(
    plotOutput("scatter")
  )
)

server <- function(input, output){

  output$scatter <- renderPlot({

    select_row_year <- df$year %in% input$range[1]:input$range[2]
    y_indices <- which(colnames(df) == input$yaxis)
    color <- which(colnames(df) == input$cat)

    ggplot(df[select_row_year, ], aes_string(x = "year",
                                             y = colnames(df)[y_indices],
                                             color = colnames(df)[color])) + 
      geom_point() +
      labs(title = "Overview", color = "Legend") +
      xlab("Year") + ylab(input$yaxis) + theme_minimal()
  })
  }

I hope it will help you. I made your legend y axis interactive.

Edit 1 :

Is it something like this that you are looking for :

ui <- fluidPage(
  sidebarPanel(
    sliderInput("range",
                "Year:", min = 1990,
                max = 2040, value = c(2000, 2020)),
    textOutput("SliderText"),
    selectInput("yaxis",
                "Y Variable",
                names(df[,c(2,7)]),
                selected = names(df)[[2]]),
    radioButtons(inputId = "cat",
                 label = "Categorized by:",
                 names(df[,3:5])),
    checkboxGroupInput(inputId = "city",
                       label = "No city choice",
                       choices = NULL,
                       selected = NULL)
  ),
  mainPanel(
    plotOutput("scatter")
  )
)

server <- function(input, output, session){
  observe({
    if(input$cat  == "city"){
     updateCheckboxGroupInput(session=session, inputId = "city",
                             label = "Select city",
                             choices = levels(df$city),
                             selected = NULL)
    }
  })

  output$scatter <- renderPlot({
    if(length(input$city) != 0){
      select_row <- df$year %in% input$range[1]:input$range[2] & df$city %in% input$city
    }else{
      select_row <- df$year %in% input$range[1]:input$range[2]
    }
    y_indices <- which(colnames(df) == input$yaxis)
    color <- which(colnames(df) == input$cat)

    ggplot(df[select_row, ], aes_string(x = "year",
                                             y = colnames(df)[y_indices],
                                             color = colnames(df)[color])) + 
      geom_point() +
      labs(title = "Overview", color = "Legend") +
      xlab("Year") + ylab(input$yaxis) + theme_minimal()
  })
  }

shinyApp(ui = ui, server = server)