Reputation: 31
I am trying to make a shiny app that produces leaflet outputs.
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 existing solutions to this question.
Do you have any advice on how to solve this issue?
Upvotes: 3
Views: 2774
Reputation: 9809
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)
Upvotes: 0
Reputation: 6579
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)
Upvotes: 3