R Shiny Leaflet Change Labels Without Redrawing - r

I've been trying to change/update the popup labels based on user input. However, the map is redrawn everytime a change is made. I tried adding a delay without success. This might be a trivial question but I've been unable to solve it.
I'm using a SpaitalPolygonsDataFrame for the base data.
If I don't clearShapes(), the fillColor overwrites itself making the fillColor darker with each successive input. Any help would be appreciated.
output$map <- renderLeaflet({
leaflet(world_spdf) %>%
addTiles() %>%
setView( lat=12.97, lng=77.59 , zoom=3) %>%
addPolygons( fillColor = Data1$Color_Code, stroke=F, fillOpacity = 0.25)
})
observe({
leafletProxy("map",data = world_spdf) %>%
clearShapes() %>%
addPolygons(fillColor = Data1$Color_Code, stroke=F, fillOpacity = 0.25, popup = filteredData1(), smoothFactor = 0.2)
})

Related

How to fix geospatial mislabeling on leaflet map within R Shiny app?

I made the following map from a data frame that contains the number of parole of each state from the years 1995-2015 per 100,000 as well as the spatial information for each state. I want to incorporate it into r shiny app to have a slider to be able to choose the specific year and view it. I got the slider to work and change the data and when you first run it works and gives you the appropriate state and number. However, when you move around the slider the geospatial labels start moving around using the reactive and different states start getting different states labels. Like the following:
The slider starts at the year 2000 and as you can see the if I move it around it, in this case 2014, now we have florida being labeled as Montana.
All these was done within the R shiny app. This is the code I have below. I have my leaflet map fully created outside the server.
server <- function(input, output) {
#Set YEAR with Slider
state_parole_year <- reactive({
state_parole %>%
filter(year == year(input$year))
})
labels_year <- reactive({paste("Parole/100000 US Adults",
state_parole_year()$state, state_parole_year()$number_on_parole_per_100000_us_adult_residents)})
output$mymap <- renderLeaflet({
state_map %>%
addTiles()%>%
addPolygons(fillColor = ~ pal(state_parole_year()$number_on_parole_per_100000_us_adult_residents),
fillOpacity = 1,
color = "blue",
opacity = 0.1,
weight = 1,
highlight = highlightOptions(
weight = 3,
color = "blue",
fillOpacity = .2,
bringToFront = TRUE),
label = labels_year())
})
}
When I run the leaflet map outside of r shiny app and change the year manually by subsetting the csv it works perfectly. The problem occurs when I try to make the labels reactive to the slider. Does someone know how I can fix the problem? Thanks!
The problem is that you build the map on unfiltered data, then display it with filtered data. There is then a switch in factors.
A quick fix is to build your map on filtered data, directly in the server() function :
output$mymap <- renderLeaflet({
leaflet(data = state_parole_year()) %>%
addTiles() %>%
setView(lng = -80,
lat = 34.5,
zoom = 4) %>%
addPolygons(fillColor = ~ pal(state_parole$number_on_parole_per_100000_us_adult_residents),
fillOpacity = 1,
color = "blue",
opacity = 0.1,
weight = 1,
highlight = highlightOptions(
weight = 3,
color = "blue",
fillOpacity = .2,
bringToFront = TRUE),
label = labels) %>%
addLegend(
position = "topright",
pal = pal,
values = ~number_on_parole_per_100000_us_adult_residents,
title = "# of U.S. Adults on Parole/100000.",
opacity = 1) %>%
addTiles()%>%
addPolygons(fillColor = ~ pal(state_parole_year()$number_on_parole_per_100000_us_adult_residents),
fillOpacity = 1,
color = "blue",
opacity = 0.1,
weight = 1,
highlight = highlightOptions(
weight = 3,
color = "blue",
fillOpacity = .2,
bringToFront = TRUE),
label = ~labels_year())
})

leafletProxy to change map with fixed fillOpacity in addPolygons, Shiny

I made a Shiny app with Year slider so that the map could update the value by Year with leafletProxy.
However, if I set fillOpacity less than 1 in addPolygons. The opacity from the next Year would overlay on the previous display. So one after one, it would fully be opaque. I could add clearShapes() after proxy %>% to overcome this, but the shape would be re-drawn and I could see the refresh.
With fillOpacity = 1, this would not be a problem, but the color is just too bright.
The first graph below is the initial view, and the second one is after sliding by one year.
Is there anyways to fix fillOpacity for each update without clearShapes()?
The parts of my codes for this are:
observe({
df <- mapSelected()
value <- as.numeric(displayValue())
proxy <- leafletProxy("mapPlot", session, data = df)
proxy %>%
addPolygons(fillColor = ~regionPal()(value), fill = TRUE,
fillOpacity = 0.6,
color = 'white', weight = 1, opacity = 0.8,
popup = paste(mapLevel(), ": ", df[[SAName()]], "<br>",
"ED counts: ", value),
highlightOptions = highlightOptions(color = 'white',
weight = 3,
opacity = 1,
bringToFront = FALSE))
})
output$mapPlot <- renderLeaflet({
leaflet() %>%
addTiles() %>%
fitBounds(lng1 = 140.99926, lng2 = 153.63873,
lat1 = -37.50508, lat2 = -28.15702)
})

Grouped layer control in Leaflet R

There is a plug-in for Leaflet JS that allows to group the layers in the layer control. https://github.com/ismyrnow/Leaflet.groupedlayercontrol
This plug-in does not seem to exist for Leaflet R but I found this post saying that there is a way to use arbitraty Leaflet JS plug-in in Leaflet R.
https://gist.github.com/jcheng5/c084a59717f18e947a17955007dc5f92
I tried to apply this method to the Leaflet.groupedlayercontrol plug-in but did not succeed. Do you have any idea how I can possibly use this plug-in or any other way to group my layers in the layercontrol generated by Leaflet R? Thank you.
You definitely can do layer control in leafletR. If you version does not have it, then you need to update, probably from the most recent GITHUB version.
I am working on a map right now that has layer controls, see the photograph. Here is the code that makes it happen. As you can see each of the addPolygons has a group = " A Name" This is where you identify the layers in the check boxes on my image.
map<-leaflet()%>%
addTiles()%>%
addPolygons(data = plotMerge,
fillColor = ~pal(plotMerge$incomePerCapita),
color = "#000000", #this is an outline color
fillOpacity = 0.8,
group="Tract",
weight = 0.2,
popup=popup)%>%
addPolygons(data = countyPoly,
fillColor = "transparent",
color = "#000000", #this is an outline color
fillOpacity = 0.8,
group="County",
popup=countyPoly#data$NAME,
weight = 2)%>%
addPolygons(data = townPoly,
fillColor = "transparent",
color = "#000000", #this is an outline color
fillOpacity = 0.8,
group="Town",
weight = .8,
popup=townPoly#data$TOWN)%>%
addPolygons(data = rphnPoly,
fillColor = "transparent",
color = "#000000", #this is an outline color
fillOpacity = 0.8,
group="Public Health Region",
weight = .8,
popup=rphnPoly#data$PHN)%>%
addLegend(pal = pal,
values = plotMerge$incomePerCapita,
position = "bottomright",
title = "State-wide Income Percentiles",
labFormat = labelFormat(digits=1))%>%
addLayersControl(
overlayGroups =c("County", "Town", "Public Health Region", "Tract"),
options = layersControlOptions(collapsed=FALSE)
)
saveWidget(map, file="map1.html", selfcontained=FALSE)
Here is what it looks like:
You can also add other controls check it out here:
Leaflet R Hidden Layers
I know this is an old question but I didn't find a good answer elsewhere - this may help others in the future.
Here is a reprex with comments that explains the code:
#load library
library(tidyverse)
library(leaflet)
#load data
data("quakes")
#map all points
# quakes %>%
# leaflet() %>%
# addProviderTiles(providers$CartoDB.Positron) %>%
# addCircleMarkers(lng = ~long, lat = ~lat, radius = 1)
#create a grouping variable -- this can be whatever you want to filter by
quakes <- quakes %>%
mutate(groups = case_when(
stations < 30 ~ 1,
stations < 50 ~ 2,
TRUE ~ 3
))
#function to plot a map with layer selection
map_layers <- function() {
#number of groups
k <- n_distinct(quakes$groups)
#base map
map <- leaflet() %>%
addProviderTiles(providers$CartoDB.Positron)
#loop through all groups and add a layer one at a time
for (i in 1:k) {
map <- map %>%
addCircleMarkers(
data = quakes %>% filter(groups == i), group = as.character(i),
lng = ~long, lat = ~lat, radius = 1
)
}
#create layer control
map %>%
addLayersControl(
overlayGroups = c(1:k),
options = layersControlOptions(collapsed = FALSE)) %>%
hideGroup(as.character(c(2:k))) #hide all groups except the 1st one
}
#plot the map
map_layers()

Delete Polygon from Leafletmap R/Shiny

I draw a Polygon on a leafletmap which I use in a shiny app.
Everytime an event is fired I want to delete the old polygon and draw the new one over it.
That does not work - I assume I use layerId wrong?
Any hints on this?
# draw polygons
observeEvent(da$ar, {
# remove polygon
removeShape(map, layerId = unique(10))
leafletProxy("myMap") %>% addPolygons(data = da$ar, stroke = TRUE,
fillOpacity = 0.5, smoothFactor = 0.5,
layerId = unique(10)
)
})
So, I go it.
When you use a layer ID on an object and draw the same object with that layerID again, the object gets deleted.
So, that is enough:
observeEvent(da$ar, {
leafletProxy("myMap") %>% addPolygons(data = da$ar, stroke = TRUE,
fillOpacity = 0.5, smoothFactor = 0.5,
layerId = "foo"
)
})

Leaflet for R clear raster with shiny

I'm wondering if their is a way to clear a raster image with shiny when the user click on some radio button. I saw there is a function to clear polygons - clearshape() but I need to do the same with my raster image.
leafletProxy("map", data = filteredData()) %>%
addRasterImage(r, colors=pal, opacity = 0.9, maxBytes = 123123123) %>%
clearShapes()
This does not work...
clearImages() can be used to replace or remove rasters - https://rdrr.io/cran/leaflet/man/remove.html:
leafletProxy("map", data = filteredData()) %>%
addRasterImage(r, colors=pal, opacity = 0.9, maxBytes = 123123123) %>%
clearImages()

Resources