How to subset a dataframe and plot with leaflet depending on inputselect in shiny

别等时光非礼了梦想. 提交于 2019-12-23 22:18:33

问题


Using Rstudio I am trying to make a shiny app that produces leaflet outputs. Note that shiny is a package I have not used before so it could be that there are other mistakes in the script than the one I am currently encountering.

I am using one dataframe with tracks of different individuals from which I want to subset and plot the track of one animal in response to inputselection.

Sample:

WhaleID     lat       long
gm08_150c   68,4276   16,5192
gm08_150c   68,4337   16,5263
gm08_150c   68,4327   16,5198
gm08_154d   68,4295   16,5243
gm08_154d   68,4313   16,5314
gm08_154d   68,4281   16,5191

The choices in the input selection are the exact names used in the .csv file, in the column WhaleID, so I would like the subset all rows with that WhaleID from the main dataframe.

After this subset I want to subset only the "long" and "lat" columns from the previously subsetted dataframe. This dataframe is then read by leaflet.

The final step is plotting these "long"and "lat" positions on a map.

Unfortunately I keep getting an error message:

Warning: Error in $: object of type 'closure' is not subsettable
Stack trace (innermost first):
    82: inherits
    81: resolveFormula
    80: derivePolygons
    79: addPolylines
    78: function_list[[i]]
    77: freduce
    76: _fseq
    75: eval
    74: eval
    73: withVisible
    72: %>%
    71: func [#15]
    70: output$map
     4: <Anonymous>
     3: do.call
     2: print.shiny.appobj
     1: <Promise>

The script I am using:

    require(shiny)
    require(leaflet)

    ##Main dataframe I want to subset depending on inputselection    
    dataframe <-read.csv2("PW_with_speedbearingturn.csv") 


    ui <- bootstrapPage( 
      tags$style(type = "text/css", "html, body {width:100%;height:100%}"),
      absolutePanel(top = 10, right = 10,
      selectInput(inputId = "whaleID", 
                  label = "Select a whale", 
                  choices = c("gm08_150c","gm08_154d"))),
      leafletOutput(outputId = "map", width = "100%", height = "700")
    ) 

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

      #?observeEvent  
      #observeEvent(input$whaleID, )
      Start <- makeIcon(
        iconUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Dark_Green_Arrow_Down.svg/480px-Dark_Green_Arrow_Down.svg.png",
        iconWidth = 22, iconHeight = 20,
        iconAnchorX = 11, iconAnchorY = 20)

      eventReactive(input$whaleID,{
                    df<-subset(dataframe, WhaleID == "input$whaleID") ## "input$whaleID" should become the WhaleID that is selected from the inputselect.

                    df<-subset(df, select = c("long", "lat")) 
      })                
      output$map <- renderLeaflet({
      leaflet() %>%
      addTiles() %>%
      addPolylines(df, lng = df$long, lat = df$lat, col = "grey", opacity = 1)%>%
      addMarkers(df, lng = first(df$long), lat = first(df$lat), icon = Start, popup = "Start")
      })
    } 

    shinyApp(ui = ui, server = server)

I believe it has to do with the eventreactive section and the subsetting part within. It has to be updated each time in response to what choice is selected from the inputselection. Unfortunately I could not find any exsisting solutions to this question.

Any advice on how to solve this issue?

Thanks in advance,

Onno


回答1:


I think you can avoid the eventReactive entirely since the renderLeaflet will be reactive on changes to input. Here is an adapted example since I don't have your data. Let me know if it does not make sense.

require(shiny)
require(leaflet)

##Main dataframe I want to subset depending on inputselection    
dataframe <- data.frame(
  abb = state.abb,
  x = state.center$x,
  y = state.center$y,
  stringsAsFactors = FALSE
)


ui <- bootstrapPage( 
  tags$style(type = "text/css", "html, body {width:100%;height:100%}"),
  absolutePanel(top = 10, right = 10,
                selectInput(inputId = "whaleID", 
                            label = "Select a state", 
                            choices = dataframe[["abb"]])),
  leafletOutput(outputId = "map", width = "100%", height = "700")
)

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

  Start <- makeIcon(
    iconUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Dark_Green_Arrow_Down.svg/480px-Dark_Green_Arrow_Down.svg.png",
    iconWidth = 22, iconHeight = 20,
    iconAnchorX = 11, iconAnchorY = 20)


  output$map <- renderLeaflet({
    df <- subset(dataframe, abb == input$whaleID)
    leaflet() %>%
      addTiles() %>%
      #addPolylines(df, lng = df$long, lat = df$lat, col = "grey", opacity = 1)%>%
      addMarkers(data = df, lng = ~x, lat = ~y, icon = Start, popup = "Start")
  })
} 

shinyApp(ui = ui, server = server)



回答2:


A little late, but for completeness and to illustrate how to do it with an eventReactive. You have to assign a name to it and then call the eventReactive (df()), otherwise it will never run.

Also if you put input$whaleID in parenthesis, it will subset the dataframe column for "input$whaleID" which is not in the dataframe i suppose. Therefore you want it without parenthesis, so it takes the selected argument from the selectInput.

You can also put the Icon outside of the server, as it doesnt have to be reactive.

require(shiny)
require(leaflet)
require(dplyr)

##Main dataframe I want to subset depending on inputselection    
dataframe <- read.csv2("PW_with_speedbearingturn.csv")

Start <- makeIcon(
  iconUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Dark_Green_Arrow_Down.svg/480px-Dark_Green_Arrow_Down.svg.png",
  iconWidth = 22, iconHeight = 20,
  iconAnchorX = 11, iconAnchorY = 20)

ui <- bootstrapPage( 
  tags$style(type = "text/css", "html, body {width:100%;height:100%}"),
  absolutePanel(top = 10, right = 10,
                selectInput(inputId = "whaleID", 
                            label = "Select a whale", 
                            choices = c("gm08_150c","gm08_154d"))),
  leafletOutput(outputId = "map", width = "100%", height = "700")
)

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

  df <- eventReactive(input$whaleID,{
    daf <- subset(dataframe, WhaleID == input$whaleID) 
    subset(daf, select = c("long", "lat")) 
  })  

  output$map <- renderLeaflet({
    leaflet() %>%
      addTiles() %>%
      addPolylines( lng = df()$long, lat = df()$lat, col = "red", opacity = 1)%>%
      addMarkers( lng = first(df()$long), lat = first(df()$lat), icon = Start, 
                  popup = "Start")
  })
} 

shinyApp(ui = ui, server = server)


来源:https://stackoverflow.com/questions/37575452/how-to-subset-a-dataframe-and-plot-with-leaflet-depending-on-inputselect-in-shin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!