Interactive choropleth map with Leaflet and Shiny - r

I'm trying to modify this repo to display a choropleth map and use a sliderInput to update the map. Everything Ok until I try to animate the slider input, nothing happens . I get this console error: input_binding_slider.js:199 Uncaught TypeError: Cannot read property 'options' of undefined.
This is the code i'm using:
library(dplyr) ; library(rgdal) ; library(leaflet)
gdp = read.csv("mexico2.csv", header= T) %>%
as.data.frame()
mexico <- readOGR("mexico.shp", layer = "mexico", encoding = "UTF-8")
ui <- shinyUI(fluidPage(
fluidRow(
column(7, offset = 1,
br(),
div(h4(textOutput("title"), align = "center"), style = "color:black"),
div(h5(textOutput("period"), align = "center"), style = "color:black"),
br())),
fluidRow(
column(7, offset = 1,
leafletOutput("map", height="530"),
br(),
actionButton("reset_button", "Reset view")),
column(3,
uiOutput("category", align = "left")))
))
server <- (function(input, output, session) {
output$category <- renderUI({
sliderInput("category", "Year:",
min=1994, max = 1999,
value = 1994, sep = "", animate=TRUE)
})
selected <- reactive({
subset(gdp,
category==input$category)
})
output$title <- renderText({
req(input$category)
paste0(input$category, " GDP by State")
})
output$period <- renderText({
req(input$category)
paste("...")
})
lat <- 23
lng <- -102
zoom <- 5
output$map <- renderLeaflet({
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
setView(lat = lat, lng = lng, zoom = zoom)
})
observe({
mexico#data <- left_join(mexico#data, selected())
qpal <- colorQuantile("YlGn", mexico$value, n = 5, na.color = "#bdbdbd")
popup <- paste0("<strong>ID: </strong>",
mexico$id,
"<br><strong>Estado: </strong>",
mexico$name,
"<br><strong>Valor: </strong>",
mexico$value)
leafletProxy("map", data = mexico) %>%
addProviderTiles("CartoDB.Positron") %>%
clearShapes() %>%
clearControls() %>%
addPolygons(data = mexico, fillColor = ~qpal(value), fillOpacity = 0.7,
color = "white", weight = 2, popup = popup) %>%
addLegend(pal = qpal, values = ~value, opacity = 0.7,
position = 'bottomright',
title = paste0(input$category, "<br>"))
})
observe({
input$reset_button
leafletProxy("map") %>% setView(lat = lat, lng = lng, zoom = zoom)
})
})
shinyApp(ui, server)
Here is a link to the shinyapp
Any help would be aprecieted.
Thanks!

It's just a naming mistake. You named your htmlOutput and your sliderOutput for "category". Internally, this messes things up.
Just change e.g. the output into
uiOutput("categoryOutput", align = "left")
and
output$categoryOutput <- renderUI({ ... })
and you should be good to go.
Edit: Full Code
library(dplyr) ; library(rgdal) ; library(leaflet)
gdp = read.csv("mexico2.csv", header= T) %>%
as.data.frame()
mexico <- readOGR("mexico.shp", layer = "mexico", encoding = "UTF-8")
ui <- shinyUI(fluidPage(
fluidRow(
column(7, offset = 1,
br(),
div(h4(textOutput("title"), align = "center"), style = "color:black"),
div(h5(textOutput("period"), align = "center"), style = "color:black"),
br())),
fluidRow(
column(7, offset = 1,
leafletOutput("map", height="530"),
br(),
actionButton("reset_button", "Reset view")),
column(3,
uiOutput("categoryOut", align = "left")))
))
server <- (function(input, output, session) {
output$categoryOut <- renderUI({
sliderInput("category", "Year:",
min=1994, max = 1999,
value = 1994, sep = "", animate=TRUE)
})
selected <- reactive({
subset(gdp,
category==input$category)
})
output$title <- renderText({
req(input$category)
paste0(input$category, " GDP by State")
})
output$period <- renderText({
req(input$category)
paste("...")
})
lat <- 23
lng <- -102
zoom <- 5
output$map <- renderLeaflet({
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
setView(lat = lat, lng = lng, zoom = zoom)
})
observe({
mexico#data <- left_join(mexico#data, selected())
qpal <- colorQuantile("YlGn", mexico$value, n = 5, na.color = "#bdbdbd")
popup <- paste0("<strong>ID: </strong>",
mexico$id,
"<br><strong>Estado: </strong>",
mexico$name,
"<br><strong>Valor: </strong>",
mexico$value)
leafletProxy("map", data = mexico) %>%
addProviderTiles("CartoDB.Positron") %>%
clearShapes() %>%
clearControls() %>%
addPolygons(data = mexico, fillColor = ~qpal(value), fillOpacity = 0.7,
color = "white", weight = 2, popup = popup) %>%
addLegend(pal = qpal, values = ~value, opacity = 0.7,
position = 'bottomright',
title = paste0(input$category, "<br>"))
})
observe({
input$reset_button
leafletProxy("map") %>% setView(lat = lat, lng = lng, zoom = zoom)
})
})
shinyApp(ui, server)

Related

update gt table with selected markers on a leaflet map in R

I'm trying to update a GT table with selected markers in a leaflet marker but for the life of me I cannot get it to update the table. There are no errors when I run the app, and there are no errors in the console when trying to select a marker.
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Sales Volume Map Report"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectizeInput("Primary_Provider","Choose Primary Provider",selected = NULL,choices = c("",unique(providers$ProviderNumber))),
selectizeInput("Compare_Group","Choose Providers to Compare",choices = c(unique(providers$ProviderNumber)),multiple = TRUE),
numericInput("radius", "Choose Radius in Miles:", 10, min = 1, max = 1000),
downloadButton("download")
),
# Show a plot of the generated distribution
mainPanel(
leafletOutput("mymap"),
gt_output(outputId = "table")
)
)
)
server <- function(input, output, session) {
my_gt_object <- reactive(gt(data %>%
dplyr::select(ProviderNumber,Facilityname,Year,Service_Line,Corazon_Category,volume) %>%
dplyr::mutate(Corazon_Category = case_when(str_detect(Corazon_Category,"PCI & PV") ~ "PCI", TRUE ~ Corazon_Category)) %>%
dplyr::filter(ProviderNumber == input$Primary_Provider | ProviderNumber %in% c(input$Compare_Group)) %>%
dplyr::group_by(ProviderNumber,Facilityname,Year,Service_Line,Corazon_Category) %>%
pivot_wider(names_from = Year,values_from = volume,names_sort = TRUE ,values_fn = \(volume) sum(volume, na.rm = TRUE)) %>%
dplyr::mutate(Case_Change = `2020` -`2019`) %>%
dplyr::mutate(Percent_change = (`2020` -`2019`) / `2020` ) %>%
dplyr::mutate(primary = case_when(ProviderNumber == input$Primary_Provider ~ 1,FALSE ~ 0)) %>%
dplyr::arrange(desc(primary),Service_Line,Corazon_Category) %>%
dplyr::select(-c(ProviderNumber)),
groupname_col = c("Service_Line","Corazon_Category")
)
output$table <- render_gt(my_gt_object())
output$mymap <- renderLeaflet({
leaflet(cords) %>%
addTiles() %>%
addCircles(data = (cords %>%
dplyr::filter(providernumber == input$Primary_Provider)),lng = ~longitude, lat = ~latitude, color = 'black', fillColor = 'Red',
radius = (input$radius*1609.344), opacity = .3) %>%
addCircleMarkers(lng = ~longitude, lat = ~latitude,
popup = ~as.character(providernumber), label = ~as.character(providernumber)) %>%
addCircleMarkers(data = (cords %>%
dplyr::filter(providernumber == input$Primary_Provider)),lng = ~longitude, lat = ~latitude,color = 'Green')
})
observeEvent(input$sitemap_marker_click, {
click <- input$sitemap_marker_click
updateSelectInput(session, "Compare_Group",
selected = c(click$id[!click$id %in% input$Compare_Group],
input$Compare_Group[input$Compare_Group != click$id]))
})

Dynamic labels on leaflet map (shiny r)

So I've been trying to add a functionality on my leaflet map in Shiny dashboard where the user would be able to choose what the popup label would show through an input checkbox statement (in this case, they would choose whether they would want to see Area of Land or Area of Water or both - default is set to both). In other words, I would like to have a list of column options that I can choose from to show on the popup label when I hover over the map.
The code I have so far is below
library(dplyr)
library(readxl)
library(shinydashboard)
library(rgdal)
library(leaflet)
library(htmltools)
download.file('https://www2.census.gov/geo/tiger/GENZ2018/shp/cb_2018_us_county_5m.zip',
'cb_2018_us_county_5m.zip')
unzip('cb_2018_us_county_5m.zip',exdir='cb_2018_us_county_5m')
download.file('https://www2.census.gov/programs-surveys/popest/geographies/2019/all-geocodes-v2019.xlsx',
'all-geocodes-v2019.xlsx')
shapes <- rgdal::readOGR("cb_2018_us_county_5m","cb_2018_us_county_5m")
df_geo <- read_excel('all-geocodes-v2019.xlsx',skip=4) %>% # the table starts from row 5
filter(`Summary Level`=='040') %>%
select(`State Code (FIPS)`, `Area Name (including legal/statistical area description)`)
colnames(df_geo) <- c('STATEFP','STATENAME')
shapes#data <- shapes#data %>%
left_join(df_geo) %>%
mutate(ALAND = as.numeric(as.character(ALAND)),
AWATER = as.numeric(as.character(AWATER)),
content = paste0('<b>',NAME,' (',STATENAME,')</b>',
'<br>Area of Land: ', ALAND,
'<br>Area of Water: ', AWATER),
NAME = as.character(NAME))
shapes <- shapes[!is.na(shapes#data$STATENAME),] # remove shapes that are not in a state (e.g., Guam)
names_state <- sort(df_geo$STATENAME)
#### UI ####
header <- dashboardHeader(
title = "Leaflet - Layer Specific Legend",
titleWidth = 300
)
body <- dashboardBody(
fluidRow(
column(width=2,
selectInput("select_state", label='Select State:',
choices = names_state,
selected= 'New York'),
style='margin-left:20px;z-index:100000'
)
),
fluidRow(
column(width = 12,
box(width = NULL, height = 620,
leafletOutput("map",height=595),
status='warning')
)
)
)
ui <- dashboardPage(
title = "Leaflet - Layer Specific Legend",
skin = 'yellow',
header,
dashboardSidebar(disable = TRUE),
body
)
#### Server ####
server <- function(input, output, session) {
#### initialize reactive values ####
rvs <- reactiveValues(poly_state=shapes[shapes#data$STATENAME == 'New York',])
#### output ####
## output: leaflet map
output$map <- renderLeaflet({
rvs$map <- rvs$poly_state %>%
leaflet() %>%
addTiles('http://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png') %>%
addPolygons(data = rvs$poly_state,
group = 'Area of Land',
weight=1, opacity = 1.0,color = 'white',
fillOpacity = 0.9, smoothFactor = 0.5,
fillColor = ~colorBin('OrRd',ALAND)(ALAND),
label = lapply(rvs$poly_state$content,HTML)) %>%
addPolygons(data = rvs$poly_state,
group = 'Area of Water',
weight=1, opacity = 1.0,color = 'grey',
fillOpacity = 0.9, smoothFactor = 0.5,
fillColor = ~colorBin('YlGnBu',AWATER)(AWATER),
label = lapply(rvs$poly_state$content,HTML)) %>%
addLayersControl(
position = "bottomright",
baseGroups = c('Area of Land','Area of Water'),
options = layersControlOptions(collapsed = TRUE)) %>%
addLegend(
"topright",
pal = colorBin('OrRd', rvs$poly_state$ALAND),
values = rvs$poly_state$ALAND
) %>%
hideGroup(c('Area of Land','Area of Water')) %>%
showGroup('Area of Land')
})
#### observe mouse events ####
## update rv when the selected state changes
observeEvent(input$select_state, {
rvs$poly_state <- shapes[shapes#data$STATENAME == input$select_state,]
})
## update legend when the selected layer group changes
observeEvent(input$map_groups, {
my_map <- leafletProxy("map") %>% clearControls()
if (input$map_groups == 'Area of Land'){
my_map <- my_map %>%
addLegend(
"topright",
pal = colorBin('OrRd', rvs$poly_state$ALAND),
values = rvs$poly_state$ALAND)
}else{
my_map <- my_map %>%
addLegend(
"topright",
pal = colorBin('YlGnBu', rvs$poly_state$AWATER),
values = rvs$poly_state$AWATER)
}
})
}
#### Run App ####
shinyApp(ui = ui, server = server)
First, you can create a data frame from your spatial data and edit your table. Here I delete the column "content".
shapes_df <- as.data.frame(shapes[,c(1:10)])
Then you create a reactive value that interacts with your input.
popup <- reactive({
return(shapes_df %>% select(input$select_column))
})
Here is a working code for you. I made some changes and commented some lines out.
library(dplyr)
library(readxl)
library(shinydashboard)
library(rgdal)
library(leaflet)
library(htmltools)
download.file('https://www2.census.gov/geo/tiger/GENZ2018/shp/cb_2018_us_county_5m.zip',
'cb_2018_us_county_5m.zip')
unzip('cb_2018_us_county_5m.zip',exdir='cb_2018_us_county_5m')
download.file('https://www2.census.gov/programs-surveys/popest/geographies/2019/all-geocodes-v2019.xlsx',
'all-geocodes-v2019.xlsx')
shapes <- rgdal::readOGR("cb_2018_us_county_5m","cb_2018_us_county_5m")
df_geo <- read_excel('all-geocodes-v2019.xlsx',skip=4) %>% # the table starts from row 5
filter(`Summary Level`=='040') %>%
select(`State Code (FIPS)`, `Area Name (including legal/statistical area description)`)
colnames(df_geo) <- c('STATEFP','STATENAME')
shapes#data <- shapes#data %>%
left_join(df_geo) %>%
mutate(ALAND = as.numeric(as.character(ALAND)),
AWATER = as.numeric(as.character(AWATER)),
content = paste0('<b>',NAME,' (',STATENAME,')</b>',
'<br>Area of Land: ', ALAND,
'<br>Area of Water: ', AWATER),
NAME = as.character(NAME))
shapes <- shapes[!is.na(shapes#data$STATENAME),] # remove shapes that are not in a state (e.g., Guam)
names_state <- sort(df_geo$STATENAME)
# here you can select which columns you want to add to your popup
shapes_df <- as.data.frame(shapes[,c(1:10)])
#### UI ####
header <- dashboardHeader(
title = "Leaflet - Layer Specific Legend",
titleWidth = 300
)
body <- dashboardBody(
fluidRow(
column(width=2,
selectInput("select_state", label='Select State:',
choices = names_state,
selected= 'New York'),
selectInput("select_column", label='Select the column you want to see in pop-up:',
choices = c(colnames(shapes#data))
),
verbatimTextOutput("output"),
style='margin-left:20px;z-index:100000'
)
),
fluidRow(
column(width = 12,
box(width = NULL, height = 620,
leafletOutput("map",height=595),
status='warning')
)
)
)
ui <- dashboardPage(
title = "Leaflet - Layer Specific Legend",
skin = 'yellow',
header,
dashboardSidebar(disable = TRUE),
body
)
#### Server ####
server <- function(input, output, session) {
rvs <- reactive({
shapes[shapes#data$STATENAME %in% input$select_state, ]
})
# we create a reactive value for popup which interacts with the input
popup <- reactive({
return(shapes_df %>% select(input$select_column))
})
#### initialize reactive values ####
#### output ####
## output: leaflet map
output$map <- renderLeaflet({
leaflet() %>%
addTiles('http://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png') %>%
addPolygons(data = rvs(),
group = 'Area of Land',
weight=1, opacity = 1.0,color = 'white',
fillOpacity = 0.9, smoothFactor = 0.5,
fillColor = ~colorBin('OrRd',rvs()#data$ALAND)(rvs()#data$ALAND),
label = paste(
colnames(popup()),": ", popup()[,1]
)
)%>%
addPolygons(data = rvs(),
group = 'Area of Water',
weight=1, opacity = 1.0,color = 'grey',
fillOpacity = 0.9, smoothFactor = 0.5,
fillColor = ~colorBin('YlGnBu',rvs()#data$AWATER)(rvs()#data$AWATER),
label = paste(
colnames(popup()),": ", popup()[,1]
)
) %>%
addLayersControl(
position = "bottomright",
baseGroups = c('Area of Land','Area of Water'),
options = layersControlOptions(collapsed = TRUE)) %>%
addLegend(
"topright",
pal = colorBin('OrRd', rvs()#data$ALAND),
values =rvs()#data$ALAND
) %>%
hideGroup(c('Area of Land','Area of Water')) %>%
showGroup('Area of Land')
})
#### observe mouse events ####
## update rv when the selected state changes
# observeEvent(input$select_state, {
# rvs()#data <- shapes[shapes#data$STATENAME == input$select_state,]
# })
## update legend when the selected layer group changes
observeEvent(input$map_groups, {
my_map <- leafletProxy("map") %>% clearControls()
if (input$map_groups == 'Area of Land'){
my_map <- my_map %>%
addLegend(
"topright",
pal = colorBin('OrRd', rvs()#data$ALAND),
values = rvs()#data$ALAND)
}else{
my_map <- my_map %>%
addLegend(
"topright",
pal = colorBin('YlGnBu', rvs()#data$AWATER),
values = rvs()#data$AWATER)
}
})
}
#### Run App ####
shinyApp(ui = ui, server = server)

possible to implement two sequential flyTo in leaflet R

I would like to create a Leaflet Map which renders at a default location, at a zoom level of 4, and then when the user clicks the go button, pans from location to another, both of which have been selected from a dropdown.
I've tried using the following code, the data for which can be found # https://github.com/eoefelein/COVID_Business_Recovery_and_Social_Capital/tree/master/socialCapitalEmployment/data
library(sf)
library(tigris)
library(shiny)
library(shinydashboard)
library(tidyverse)
library(leaflet)
# data loading and processing
USA <- st_read(dsn = 'data/cb_2018_us_county_5m.shp')
counties_sf <- st_as_sf(USA)
counties_reproject_sf <- st_transform(counties_sf, 4326) %>% filter(COUNTYFP < 60010)
emp_rate <- read_csv('data/synthetic_emp_rate_pred.csv')
emp_rate$countyfips <- sprintf("%05d", emp_rate$countyfips)
states_sf_coef <- geo_join(counties_reproject_sf, emp_rate, "GEOID", "countyfips", how='inner')
ui <- fluidPage(
dashboardPage(
dashboardHeader(title="Employee Rate Data"),
dashboardSidebar(
sidebarMenu(
menuItem(
"Maps",
tabName = "maps",
icon=icon("globe")
)
)
),
dashboardBody(
tabItems(
tabItem(
tabName = "maps",
tags$style(type="text/css","#all_airports {height:calc(100vh - 80px) !important;}"),
fluidRow(column(4),
column(8,
selectInput(inputId = "FromCounty",
label="from",
choices=c(unique(emp_rate$countyname)),
selected = 'Travis County, Texas'
),
selectInput(inputId = "ToCounty",
label = "to",
choices=c(unique(emp_rate$countyname))
))),
actionButton("zoomer","go"),
leafletOutput("map")
)
)
)
)
)
server <- function(input, output, session) {
# map
output$map <- renderLeaflet({
mypal <- colorNumeric(palette="viridis", domain=states_sf_coef$rand_pred, na.color="transparent")
# mypalette(c(45,43))
leaflet() %>%
addProviderTiles("OpenStreetMap.Mapnik") %>%
setView(lat = 38.2393,
lng = -96.3795,
zoom = 4) %>%
addPolygons(
data = states_sf_coef,
fillColor = ~mypal(rand_pred),
# fillColor = ~ mypal(data$value),
stroke = FALSE,
smoothFactor = 0.2,
fillOpacity = 0.3,
popup = paste(
"Region: ",
states_sf_coef$countyname,
"<br>",
"Social Index: ",
states_sf_coef$rand_pred,
"<br>"
)
)
# %>%
# addLayersControl(
# baseGroups = c("Employment Prediction Data (default)", "To-From"),
# options = layersControlOptions(collapsed = FALSE)
# )
})
map_proxy <- leafletProxy("map")
observeEvent(input$zoomer, { # add Smith, county, kansas and default to zoom = 1?
# fromCounty
fromCountyInput <- reactive({
states_sf_coef %>% dplyr::filter(countyname == input$FromCounty)
})
fromData <- fromCountyInput()
fromCoords <- st_coordinates(st_centroid(fromData$geometry))
# toCounty
toCountyInput <- reactive({
states_sf_coef %>% dplyr::filter(countyname == input$ToCounty)
})
toData <- toCountyInput()
toCoords <- st_coordinates(st_centroid(toData$geometry))
map_proxy %>%
flyTo(lng = fromCoords[1], lat = fromCoords[2], zoom = 10)
flyTo(lng = toCoords[1], lat = toCoords[2], zoom = 10)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Right now I'm getting the following error:
Warning: Error in dispatch: argument "map" is missing, with no default. Any guidance would be much appreciated!
I can't access your data to check that this works but I found a solution my (similar) problem by using shinyjs::delay(). This requires that you include the useShinyjs() in the ui as I have done below.
library(sf)
library(tigris)
library(shiny)
library(shinydashboard)
library(tidyverse)
library(leaflet)
library(shinyjs)
# data loading and processing
USA <- st_read(dsn = 'data/cb_2018_us_county_5m.shp')
counties_sf <- st_as_sf(USA)
counties_reproject_sf <- st_transform(counties_sf, 4326) %>% filter(COUNTYFP < 60010)
emp_rate <- read_csv('data/synthetic_emp_rate_pred.csv')
emp_rate$countyfips <- sprintf("%05d", emp_rate$countyfips)
states_sf_coef <- geo_join(counties_reproject_sf, emp_rate, "GEOID", "countyfips", how='inner')
ui <- fluidPage(
dashboardPage(
useShinyjs(),
dashboardHeader(title="Employee Rate Data"),
dashboardSidebar(
sidebarMenu(
menuItem(
"Maps",
tabName = "maps",
icon=icon("globe")
)
)
),
dashboardBody(
tabItems(
tabItem(
tabName = "maps",
tags$style(type="text/css","#all_airports {height:calc(100vh - 80px) !important;}"),
fluidRow(column(4),
column(8,
selectInput(inputId = "FromCounty",
label="from",
choices=c(unique(emp_rate$countyname)),
selected = 'Travis County, Texas'
),
selectInput(inputId = "ToCounty",
label = "to",
choices=c(unique(emp_rate$countyname))
))),
actionButton("zoomer","go"),
leafletOutput("map")
)
)
)
)
)
server <- function(input, output, session) {
# map
output$map <- renderLeaflet({
mypal <- colorNumeric(palette="viridis", domain=states_sf_coef$rand_pred, na.color="transparent")
# mypalette(c(45,43))
leaflet() %>%
addProviderTiles("OpenStreetMap.Mapnik") %>%
setView(lat = 38.2393,
lng = -96.3795,
zoom = 4) %>%
addPolygons(
data = states_sf_coef,
fillColor = ~mypal(rand_pred),
# fillColor = ~ mypal(data$value),
stroke = FALSE,
smoothFactor = 0.2,
fillOpacity = 0.3,
popup = paste(
"Region: ",
states_sf_coef$countyname,
"<br>",
"Social Index: ",
states_sf_coef$rand_pred,
"<br>"
)
)
# %>%
# addLayersControl(
# baseGroups = c("Employment Prediction Data (default)", "To-From"),
# options = layersControlOptions(collapsed = FALSE)
# )
})
map_proxy <- leafletProxy("map")
observeEvent(input$zoomer, { # add Smith, county, kansas and default to zoom = 1?
# fromCounty
fromCountyInput <- reactive({
states_sf_coef %>% dplyr::filter(countyname == input$FromCounty)
})
fromData <- fromCountyInput()
fromCoords <- st_coordinates(st_centroid(fromData$geometry))
# toCounty
toCountyInput <- reactive({
states_sf_coef %>% dplyr::filter(countyname == input$ToCounty)
})
toData <- toCountyInput()
toCoords <- st_coordinates(st_centroid(toData$geometry))
map_proxy %>%
flyTo(lng = fromCoords[1], lat = fromCoords[2], zoom = 10)
delay(5000, {map_proxy %>% flyTo(lng = toCoords[1], lat = toCoords[2], zoom = 10)})
})
}
# Run the application
shinyApp(ui = ui, server = server)

R Shiny/Leaflet Jump to filtered Markers

I'm plotting bicycle accidents in Switzerland in a Shiny App. Filtering the accidents by canton works but I want to recenter the map every time a new canton is chosen. I think flyTo() would do the trick but I cannot make it work.
if(!require('leaflet')){install.packages('leaflet'); library('leaflet')}
if(!require('shiny')){install.packages('shiny'); library('shiny')}
if(!require('tidyverse')){install.packages('tidyverse'); library('tidyverse')}
veloaua <- read_csv(file = 'https://raw.githubusercontent.com/nicoschreibt/velovaua/master/veloaua_github.csv?token=AP64ETIQHSXQADG2GKFM6B3BEVLM6')
veloaua <- veloaua[sample(1:length(veloaua$AccidentType), size = 100),]
ui <- fluidPage(
selectInput(inputId = "kant",
label = "Welchen Kanton willst du sehen?",
choices = unique(veloaua$CantonCode)),
leafletOutput("mymap")
)
server <- function(input, output, session) {
output$mymap <- renderLeaflet({
leaflet() %>%
addProviderTiles(providers$Stamen.Toner, options = providerTileOptions(minZoom = 8, maxZoom = 20))%>%
clearBounds() %>%
addMarkers(data = veloaua,
lng = ~wgs84_e,
lat = ~wgs84_n,
icon = icons,
popup = veloaua$poptext,
group = "main")
})
observeEvent(input$kant, {
leafletProxy("mymap")%>%
clearGroup("main") %>%
addMarkers(data = veloaua[veloaua$CantonCode == input$kant,],
lng = ~wgs84_e,
lat = ~wgs84_n,
popup = ~poptext,
group = "main",
clusterOptions = markerClusterOptions(
removeOutsideVisibleBounds = TRUE,
showCoverageOnHover = FALSE,
disableClusteringAtZoom = 15)) %>%
leaflet::flyTo(map = "mymap",
lng = veloaua$wgs84_e[veloaua$CantonCode == input$kant],
lat = veloaua$wgs84_n[veloaua$CantonCode == input$kant])
}
)
}
shinyApp(ui = ui, server = server)
Found a solution:
ui <- fluidPage(
selectInput(inputId = "kant",
label = "Welchen Kanton willst du sehen?",
choices = unique(veloaua$CantonCode)),
leafletOutput("mymap")
)
server <- function(input, output, session) {
center <- reactive({
subset(x = veloaua, CantonCode == input$kant)
# or whatever operation is needed to transform the selection
# to an object that contains lat and long
})
output$mymap <- renderLeaflet({
leaflet() %>%
addProviderTiles(providers$Stamen.Toner, options = providerTileOptions(minZoom = 8, maxZoom = 20))%>%
clearBounds() %>%
addMarkers(data = veloaua,
lng = ~wgs84_e,
lat = ~wgs84_n,
icon = icons,
popup = veloaua$poptext,
group = "main")
})
observeEvent(input$kant, {
leafletProxy("mymap")%>%
clearGroup("main") %>%
addMarkers(data = veloaua[veloaua$CantonCode == input$kant,],
lng = ~wgs84_e,
lat = ~wgs84_n,
popup = ~poptext,
group = "main",
clusterOptions = markerClusterOptions(
removeOutsideVisibleBounds = TRUE,
showCoverageOnHover = FALSE,
disableClusteringAtZoom = 15)) %>%
setView(lng = center()$wgs84_e[1], lat = center()$wgs84_n[1], zoom = 15)
}
)
}
shinyApp(ui = ui, server = server)

Click-on ability on leaflet heatmap

I have a shiny app which displayes a leaflet heatmap. I would like to know if is possible to click on a certain point of the map and get the relative row(s) of the dataframe in a data table below.
library(shiny)
library(DT)
library(leaflet)
library(leaflet.extras)
# ui object
ui <- fluidPage(
titlePanel(p("Spatial app", style = "color:#3474A7")),
sidebarLayout(
sidebarPanel(
),
mainPanel(
leafletOutput("map"),
tableOutput("myTable")
)
)
)
# server()
server <- function(input, output, session) {
data <- reactiveValues(clickedMarker=NULL)
output$map<-renderLeaflet({
leaflet(quakes) %>%
addProviderTiles(providers$CartoDB.DarkMatter) %>%
setView( 178, -20, 5 ) %>%
addHeatmap(
lng = ~long, lat = ~lat, intensity = ~mag,
blur = 20, max = 0.05, radius = 15
) %>%
addCircleMarkers(lng = quakes$long, lat = quakes$lat, layerId = quakes$depth,
fillOpacity = 0, weight = 0,
popup = paste("Depth:", quakes$depth, "<br>",
"Stations:", quakes$stations),
labelOptions = labelOptions(noHide = TRUE))
})
# observe the marker click info and print to console when it is changed.
observeEvent(input$map_marker_click,{
print("observed map_marker_click")
data$clickedMarker <- input$map_marker_click
print(data$clickedMarker)
output$myTable <- renderTable({
return(
subset(quakes,depth == data$clickedMarker$depth)
)
})
})
}
# shinyApp()
shinyApp(ui = ui, server = server)
As update to my comment, I think the issue is that when you are trying to subset the dataset at the end, the rows you trying to match with are actually $id and not $depth - I think this is because when you call layerId = quakes$depth it creates an id to match on.
I think this does what you want:
library(shiny)
library(DT)
library(leaflet)
library(leaflet.extras)
# ui object
ui <- fluidPage(
titlePanel(p("Spatial app", style = "color:#3474A7")),
sidebarLayout(
sidebarPanel(
),
mainPanel(
leafletOutput("map"),
tableOutput("myTable")
)
)
)
# server()
server <- function(input, output, session) {
data <- reactiveValues(clickedMarker=NULL)
output$map<-renderLeaflet({
leaflet(quakes) %>%
addProviderTiles(providers$CartoDB.DarkMatter) %>%
setView( 178, -20, 5 ) %>%
addHeatmap(
lng = ~long, lat = ~lat, intensity = ~mag,
blur = 20, max = 0.05, radius = 15
) %>%
addCircleMarkers(lng = quakes$long, lat = quakes$lat, layerId = quakes$depth,
fillOpacity = 0, weight = 0,
popup = paste("Depth:", quakes$depth, "<br>",
"Stations:", quakes$stations),
labelOptions = labelOptions(noHide = TRUE))
})
# observe the marker click info and print to console when it is changed.
observeEvent(input$map_marker_click,{
print("observed map_marker_click")
data$clickedMarker <- input$map_marker_click
print(data$clickedMarker)
output$myTable <- renderTable({
return(
subset(quakes, depth == data$clickedMarker$id)
)
})
})
}
# shinyApp()
shinyApp(ui = ui, server = server)
giving:
If you check the console output you will see the id subsetted (not depth):
[1] "observed map_marker_click"
$id
[1] 46
$.nonce
[1] 0.3895379
$lat
[1] -13.66
$lng
[1] 172.23

Resources