Search code examples
rshinygooglevis

Gauge chart from GoogleVis displaying in browser but on shiny app I get the error $ operator is invalid for atomic vectors


I am trying to make a shiny app where I can select a location on the map and display a gauge chart for each corresponding location. I have been able to make the app reactive but the googlevis gauge display appears on the browser instead of in the app. In the app I get the error $ operator is invalid for atomic vectors. I tried converting the data into a dataframe but I am still getting this error. the code is as follows

library(shiny)
library(leaflet)
library(shinydashboard)
library(dplyr)
library(googleVis)

#Making the Dataframe
locations<-c("A","B","C")
x<-c(36.05617,36.05626,36.05634)
y<-c(-2.1007,-2.05553,-2.01035)
yield<-c(5.86,3.06,1.07)
df<-data.frame(locations,x,y,yield)

################## Defining UI for application ############################
  ui <- shinyUI(dashboardPage(title = "Yield Lookup",
                     dashboardHeader(title = "Crop Yield (Tonnes per Hectare)",titleWidth = 350),
                     dashboardSidebar(
                       sidebarMenu(
                         menuItem("Map Dashboard", tabName = "datavis",  icon = icon("map", verify_fa = FALSE)),
                         menuItem("Select by Location Name", icon = icon("leaf"),
                                  selectizeInput("locations", "Click on Location", choices = levels(factor(df$locations)))
                         )
                       )
                     ),
                     dashboardBody(
                       tabItems(
                         tabItem(tabName = "datavis",
                                 h4("Map and Plot"),
                                 fluidRow(box(width= 8,  leafletOutput("map", height = 800)),
                                          box("Gauge for crop yield by area",width = 4, htmlOutput("myplot")))
                         )
                       )
                     )
  )
  )
  
  ################## Defining Server for application ############################
  server<- shinyServer(function(input,output, session){
    ## Sub data     
    lo<-reactive({
      
    })
    
    locat_data <- reactive({
     df[df$locations %in% input$locations,]
      })  
    
    output[["myplot"]] <- renderGvis({

      newdf<-locat_data()%>%select(locations, yield)
      newdf<-as.data.frame(newdf)

      Gauge <-  gvisGauge(as.data.frame(newdf), 
                          options=list(min=0, max=6, greenFrom=4,
                                       greenTo=6, yellowFrom=2, yellowTo=4,
                                       redFrom=0, redTo=2, width=400, height=300))
      plot(Gauge)
     
      
    })
    
    
    output$map <- renderLeaflet({
      leaflet(df) %>% 
        addTiles() %>%
        addCircleMarkers(lng = ~x, lat = ~y, layerId = ~locations, color = "blue", radius = 3) %>%
        addCircles(lng = ~x, lat = ~y, weight = 1,
                   radius = 1, label = ~locations
        )
      
    })
    observeEvent(input$locations,{
      updateSelectInput(session, "locations", "Click on Locations", 
                        choices = levels(factor(df$locations)), 
                        selected = c(input$locations))
    })
    
    observeEvent(input$map_marker_click, {
      click <- input$map_marker_click
      location <- df[which(df$y == click$lat & df$x == click$lng), ]$locations
      updateSelectInput(session, "locations", "Click on Location", 
                        choices = levels(factor(df$locations)), 
                        selected = c(input$locations, location))
    })
    
  })

  shinyApp(ui=ui, server = server)

I am not sure where I am going wrong. Please help.


Solution

  • You were very close.

    Just drop the plot() and leave Gauge in the server section. (Alternatively drop the Gauge <- and Gauge on the next line and just leave gvisGauge())

    library(shiny)
    library(leaflet)
    library(shinydashboard)
    library(dplyr)
    library(googleVis)
    
    #Making the Dataframe
    locations<-c("A","B","C")
    x<-c(36.05617,36.05626,36.05634)
    y<-c(-2.1007,-2.05553,-2.01035)
    yield<-c(5.86,3.06,1.07)
    df<-data.frame(locations,x,y,yield)
    
    ################## Defining UI for application ############################
      ui <- shinyUI(dashboardPage(title = "Yield Lookup",
                         dashboardHeader(title = "Crop Yield (Tonnes per Hectare)",titleWidth = 350),
                         dashboardSidebar(
                           sidebarMenu(
                             menuItem("Map Dashboard", tabName = "datavis",  icon = icon("map", verify_fa = FALSE)),
                             menuItem("Select by Location Name", icon = icon("leaf"),
                                      selectizeInput("locations", "Click on Location", choices = levels(factor(df$locations)))
                             )
                           )
                         ),
                         dashboardBody(
                           tabItems(
                             tabItem(tabName = "datavis",
                                     h4("Map and Plot"),
                                     fluidRow(box(width= 8,  leafletOutput("map", height = 800)),
                                              box("Gauge for crop yield by area",width = 4, htmlOutput("myplot")))
                             )
                           )
                         )
      )
      )
      
      ################## Defining Server for application ############################
      server<- shinyServer(function(input,output, session){
        ## Sub data     
        lo<-reactive({
          
        })
        
        locat_data <- reactive({
         df[df$locations %in% input$locations,]
          })  
        
        output[["myplot"]] <- renderGvis({
    
          newdf<-locat_data()%>%select(locations, yield)
          newdf<-as.data.frame(newdf)
    
          Gauge <-  gvisGauge(as.data.frame(newdf), 
                              options=list(min=0, max=6, greenFrom=4,
                                           greenTo=6, yellowFrom=2, yellowTo=4,
                                           redFrom=0, redTo=2, width=400, height=300))
          Gauge
         
          
        })
        
        
        output$map <- renderLeaflet({
          leaflet(df) %>% 
            addTiles() %>%
            addCircleMarkers(lng = ~x, lat = ~y, layerId = ~locations, color = "blue", radius = 3) %>%
            addCircles(lng = ~x, lat = ~y, weight = 1,
                       radius = 1, label = ~locations
            )
          
        })
        observeEvent(input$locations,{
          updateSelectInput(session, "locations", "Click on Locations", 
                            choices = levels(factor(df$locations)), 
                            selected = c(input$locations))
        })
        
        observeEvent(input$map_marker_click, {
          click <- input$map_marker_click
          location <- df[which(df$y == click$lat & df$x == click$lng), ]$locations
          updateSelectInput(session, "locations", "Click on Location", 
                            choices = levels(factor(df$locations)), 
                            selected = c(input$locations, location))
        })
        
      })
    
      shinyApp(ui=ui, server = server)