I've built the following app https://iseak.shinyapps.io/Mapa/
and I would like to switch from tmap to leaflet for the map portion of the app because I've run into some limitations (I'd like fancier popups and some other stuff).
Currently the map is working with tmap using the following code:
output$map = renderLeaflet({
tm <- tm_shape(subsetData()) +
tm_fill(selvar(), palette=colores(),
alpha=0.95,
breaks=breaks(),
id="Zona",
popup.vars=c(" "="popover"),
popup.format=list(digits=2),
legend.show = F,
labels=c(" "=selvar())
) +
tm_borders() +
tmap_options(basemaps = "CartoDB.Positron"
)
tmap_leaflet(tm) %>%
removeLayersControl()
})
My starting point when trying to use leaflet directly is:
output$map = renderLeaflet({
leaflet(data=subsetData()) %>%
addProviderTiles("CartoDB.Positron") %>%
clearShapes() %>%
clearControls() %>%
addPolygons(data = subsetData(),
fillColor = ~colores()(selvar()),
fillOpacity = 0.9,
weight = 2)
})
But I keep getting errors. I would appreciate some pointers on how to easily switch from tmap to leaflet and how to use reactive values inside the leaflet call. Thanks!
This question is quite open. I think the leaflet website has quite good example code (https://rstudio.github.io/leaflet/). Browse through the left menu.
When it come to reactivity you don't need brackets to use variable created by reactiveValues; in case of reactive() you need some.
Looking at your code I'm not sure what is behind color() and selvar(). Assuming selvar() is the number for the color scale my approach would have been something like this:
selvar <- reactiveValues(n=c(1:10)
output$map = renderLeaflet({
pal <- leaflet::colorBin(brewer.pal(9,"Blues"), domain = selvar, bins = 7, na.color = "gray")
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data=shp,
fillColor = ~pal(selvar),
fillOpacity = 0.9,
weight = 2)
You can specify your shape data in leaflet() or in addPolygons(). Using the latter allows to use different shape file tables. Finally, another useful pointer is leafletProxy('map') which would work well with the year buttons underneath the map for fast updates.
Related
Anyone created a leaflet map in Code Workbook using r-Leaflet? I have a functioning script that runs (also double checked in R) but how do I get it to visualise and then use in a Report etc. I have tried various tweaks on what may get it to run but no success - any ideas
leaflet_map <- function(map_data) {
library(leaflet)
data<-map_data
# first cut the continuous variable into bins
# these bins are now factors
data$Fill_rateLvl <- cut(data$Fill_rate,
c(0,.5,0.6,0.7,0.8,0.9,1), include.lowest = T,
labels = c('<50%', '50-60%', '60-70%', '70-80%', '80-90%','90-100%'))
# then assign a palette to this using colorFactor
# in this case it goes from red for the smaller values to yellow and green
# standard stoplight for bad, good, and best
FillCol <- colorFactor(palette = 'RdYlGn', data$Fill_rateLvl)
m<-leaflet() %>%
addTiles() %>%
addProviderTiles(providers$CartoDB.Positron)%>%
setView(lng = -0, lat = 50, zoom = 8) %>%
addCircleMarkers(data = data, lat = ~lat, lng = ~long,
color = ~FillCol(Fill_rateLvl), popup = data$Lead_employer,
radius = ~sqrt(Fill_rate*50), group = 'Fill rate') %>%
addLegend('bottomright', pal = FillCol, values = data$Fill_rateLvl,
title = 'Fill rate for next two weeks',
opacity = 1)
return(NULL)
}
I am not familiar with R in code workbook, but it sounds to me that you need to materialize your leaflet map as a dataset and then consume it in some sort of map compatible UI.
For example slate has a map widget which is backed by leaflets. You can find documentation and examples for it in https://www.palantir.com/docs/foundry/slate/widgets-map/
The background to the question is as follows:
I have a shiny app that presents data on a leaflet map. That data can be filtered and presented in different ways. However, when the user zooms in and/or moves the map, and THEN filters the data, the map will revert back to the initial map view:
output$mymap <- renderLeaflet({
leaflet() %>%
setView(lng = 0, lat = 30, zoom = 4) %>% #setting the view over ~ center of North America
addTiles(options = providerTileOptions(noWrap = TRUE))
})
What I am looking for is some way of returning the position of the map such that when the data is updated in a proxy leaflet function I can set the view as well. The following is what I'm trying to achieve (I've made up a move equivalent of input$mymap_click).
observeEvent(input$mymap_move, {
move <- input$mymap_move
mlat <- move$lat
mlon <- move$lon
mzoom <- move$zoom
leafletProxy('mymap') %>%
setView(lng = mlng, lat = mlat, zoom = mzoom) %>%
addMarkers(data = data.join,
lat = data.join$a.lat,
lng = data.join$a.lon,
icon = icon.func[data.join$SYMBOL_CODE],
popup = data.join$ANCHOR)
})
Once your map is initialised, you can access the current state of your map via input$mymap_center and input$mymap_zoom (and if you wish you can access input$mymap_bounds)
There are just 2 things you need to pay attention to:
You have to check whether initialisation is complete yet, and if not give manual parameters (or Shiny won't know what starting position to use)
Unless you isolate the lookup, your map will re-render every time you change the view, which is probably not what you want (it makes your app really slow, and unworkable to the user)
So putting it all together, I think this code should do what you wish:
output$mymap <- renderLeaflet({
isolate({
if ("mymap_center" %in% names(input)) {
mapparams <- list(center = input$mymap_center,
zoom = input$mymap_zoom)
} else {
mapparams <- list(center = list(lng=0, lat=30),
zoom = 4) #setting the view over ~ center of North America
}
})
leaflet() %>%
setView(lng = mapparams$center$lng, lat = mapparams$center$lat, zoom = mapparams$zoom) %>%
addTiles(options = providerTileOptions(noWrap = TRUE))
})
I made a map of London using https://data.london.gov.uk/dataset/statistical-gis-boundary-files-london and shiny and R and leaflet. I added an attribute to the shapefile, and now want to be able to highlight the shapefile and print information when the user clicks on a specific polygon.
I looked at shiny leaflet ploygon click event, Marker mouse click event in R leaflet for shiny, and How to implement input$map_marker_click correctly?, and know I need to use ObserveEvent, but have not been able to implement it correctly.
My code is:
library(shiny)
library("rgdal")
library(leaflet)
shapeData <- readOGR('statistical-gis-boundaries-london/ESRI/LSOA_2004_London_Low_Resolution.shp')
shapeData <- spTransform(shapeData, CRS("+proj=longlat +ellps=GRS80"))
shapeData$col=sample(c('red','yellow','green'),nrow(shapeData),1) #add some value you want to map
borough=read.csv('BoroughCentres.csv')
ui=fluidPage(
fluidPage(
leafletOutput('LSOAMap'),
p(),
selectInput('LANAME','Borough',
choices = unique(shapeData$LA_NAME))
)
)
server=function(input, output) {
output$LSOAMap <- renderLeaflet({
llong=borough[borough$Borough==input$LANAME,3]
llat=borough[borough$Borough==input$LANAME,4]
bor=subset(shapeData,shapeData$LA_NAME %in% input$LANAME)
leaflet() %>% addTiles() %>%
setView(lng = llong, lat=llat,zoom=13) %>%
addPolygons(data=bor,weight=2,col = 'black',fillOpacity = 0.2,fillColor = bor$col,
highlightOptions = highlightOptions(color='white',weight=1,
bringToFront = TRUE)) %>%
addMarkers(lng = llong,lat=llat,popup=input$LANAME)
})
}
shinyApp(ui, server)
I tried adding, along with session as an argument:
observe({
click <- input$map_marker_click
if (is.null(click))
return()
print(click)
text <-
paste("Lattitude ",
click$lat,
"Longtitude ",
click$lng)
leafletProxy(mapId = "LSOAMap") %>%
clearPopups() %>%
addPopups(dat = click, lat = ~lat, lng = ~lng, popup = text)
# map$clearPopups()
# map$showPopup(click$latitude, click$longtitude, text)
})
to no avail.
What I want is that when a user highlights a specific shape, text pops up and shows the corresponding STWARDNAME from the shapefile.
the first few lines of borough are:
> head(borough)
Borough LA_CODE long lat
1 City of London E09000001 -0.09194991 51.51814
2 Barking and Dagenham E09000002 0.13064556 51.54764
3 Barnet E09000003 -0.20416711 51.61086
4 Bexley E09000004 0.13459320 51.45981
5 Brent E09000005 -0.26187070 51.55697
6 Bromley E09000006 0.03734663 51.38836
You are pretty close but have a few syntax issues which I think are tripping you up.
First you are not properly selecting what STWARDNAME you want from your SPDF so there is no way for R to know which one to show. I added this line
popup = subset(shapeData, LA_NAME == input$LANAME )$STWARDNAME
Also you were passing highlightOptions as an option when it should just be highlight
Finally since you were more interested in mouseover for a polygon, I removed the popup marker and changed to highlight so that the name is shown when you mouseover the polygon:
leaflet() %>% addTiles() %>%
setView(lng = llong, lat=llat,zoom=13) %>%
addPolygons(data=bor,weight=2,col = 'black',fillOpacity = 0.2,fillColor = bor$col,
highlight = highlightOptions(color='white',weight=1,
bringToFront = TRUE), label= popup)
Which yields:
#Stedy answer was brilliant, and better, I just went a different way. I added in a layer id vector, and a popup decision to find the STWARDNAME
lid=as.vector(row.names(bor#data))
pu=bor#data[row.names(bor#data)==lid,'STWARDNAME']
, then added in two arguments while making the map layerId = lid,popup = pu,. The pop up showed when the user clicked on an area
bor=subset(shapeData,shapeData$LA_NAME %in% input$LANAME)
lid=as.vector(row.names(bor#data))
pu=bor#data[row.names(bor#data)==lid,'STWARDNAME']
leaflet() %>% addTiles() %>%
setView(lng = llong, lat=llat,zoom=13) %>%
addPolygons(data=bor,weight=2,col = 'black',fillOpacity = 0.2,fillColor = bor$col,
layerId = lid,popup = pu,
highlightOptions = highlightOptions(color='white',weight=1,
bringToFront = TRUE)) %>%
addMarkers(lng = llong,lat=llat,popup=input$LANAME)
Whenever the mouse pointer is hovering over a leaflet map, the browser does not scroll up or down. This happens even when I affix minZoom and maxZoom to an equal value. Is there a solution to this?
php.poverty.map.2009 <-
leaflet(options = leafletOptions(minZoom = 12, maxZoom = 12)) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data = php.df.polygon.2009,
fillColor = ~php.pal.2009(percent),
color = "#b2aeae", # must use hex colors
fillOpacity = 0.7,
weight = 0.3,
smoothFactor = 0.2,
popup = php.popup.2009) %>%
addLegend(pal = php.pal.2009,
values = php.df.polygon.2009$percent,
position = "bottomright",
title = "Percent of Households <br> Living below Poverty <br> (Census, 2009)",
labFormat = labelFormat(suffix = "%"))
php.poverty.map.2009
In my second attempt at answering this question I came across the leaflet.extras package which implements a selection of leaflet plugins in R. One of these is the Leaflet.Sleep plugin which can be implemented by adding the suspendScroll() function to your leaflet map in R.
Basic Example
First, install leaflet.extras using devtools::install_github('bhaskarvk/leaflet.extras').
library(leaflet)
library(leaflet.extras)
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
suspendScroll()
See this page for an example.
A Leaflet map has a documented scrollWheelZoom option that allows you to disable scrollwheel interactions (but still allows other ways to zoom the map, such as the zoom buttons).
In plain Javascript, this is used like var map = L.map({ scrollWheelZoom: false }). I'm not well versed in R, but you should try leaflet(options = leafletOptions(scrollWheelZoom = false)) or variations thereof.
I think your zoom options might need to go in the providerTiles function. I.e. addProviderTiles("CartoDB.Positron", options = providerTileOptions(minZoom=12, maxZoom=12))
Quick question all.
I have some data in sql server which i have loaded into RStudio. I have made a barchart for the data and now i am using leaflet library with the use of latitude and longitude to plot a point on the map. I want to be able to use popup to show a barchart in it when the user clicks on the point.
BarChart code (maybe this is a problem because i am using googleVis library so not sure if i can use this in the popup. but again this is the most appropriate bar graph i can make and need- other suggestions could be helpful as i am not a professional in R libraries yet)
Switzerland <- sqlQuery(con, "sql query")
SwitzerlandChart <- gvisBarChart(Switzerland, options = list(height=200))
For the graph plot the code is:
m <- leaflet() %>%
addTiles() %>% # Add default OpenStreetMap map tiles
addCircles(lng=8.498868, lat=46.9221, popup=paste(plot(SwitzerlandChart)))
When i run this code it opens a webpage to view my barplot.
Then i run the following:
m #Prints the graph
This prints the graph with the point in the desired location but the popup shows me a webpage instead which also only i can open.
I want to be able to plot the bargraph inside the popup please.
Hope someone can help
Maybe a little late but here's a solution. The addPopups() function in library(leaflet) seems to be able to handle .svg files. Therefore, you could simply save your plot using svg() and then read it again using readLines(). Here's a reproducible example using library(mapview):
library(lattice)
library(mapview)
library(sp)
data(meuse)
coordinates(meuse) <- ~x+y
proj4string(meuse) <- CRS("+init=epsg:28992")
clr <- rep("grey", length(meuse))
fldr <- tempfile()
dir.create(fldr)
pop <- lapply(seq(length(meuse)), function(i) {
clr[i] <- "red"
p <- xyplot(meuse$cadmium ~ meuse$copper,
col = clr, pch = 20, alpha = 0.7)
svg(filename = paste(fldr, "test.svg", sep = "/"),
width = 250 * 0.01334, height = 250 * 0.01334)
print(p)
dev.off()
tst <- paste(readLines(paste(fldr, "test.svg", sep = "/")), collapse = "")
return(tst)
})
mapview(meuse, popup = pop, cex = "cadmium")
You will see that each popup is a scatterplot. As for a leaflet example, consider this:
content <- pop[[1]]
leaflet() %>% addTiles() %>%
addPopups(-122.327298, 47.597131, content,
options = popupOptions(closeButton = FALSE)
)
In case you need the plot to be interactive, you could have a look at library(gridSVG) which is able to produce interactive svg plots from e.g. lattice or ggplot2 plots.
UPDATE:
library(mapview) now has designated functionality for this:
popupGraph: to embed lattice, ggplot2 or interactive hatmlwidgets based plots.
popupImage: to embed local or remote (web) images
This is currently only available in the development version of mapview which can be installed with:
devtools::install_github("environmentalinformatics-marburg/mapview", ref = "develop"
This may be a little late too, but here is a full leaflet implementation. I first create the plot and then use the popupGraph function to add it in.
# make a plot of the two columns in the dataset
p <- xyplot(Home ~ Auto, data = Jun, col = "orange", pch = 20, cex = 2)
# make one for each data point
p <- mget(rep("p", length(Jun)))
# color code it so that the corresponding points are dark green
clr <- rep("orange", length(Jun))
p <- lapply(1:length(p), function(i) {
clr[i] <- "dark green"
update(p[[i]], col = clr)
})
# now make the leaflet map
m1 <- leaflet() %>%
addTiles() %>%
setView(lng = -72, lat = 41, zoom = 8) %>%
# add the markers for the Jun dataset
# use the popupGraph function
addCircleMarkers(data = Jun, lat = ~Lat, lng = ~Lon,
color = ~beatCol(BeatHomeLvl), popup = popupGraph(p),
radius = ~sqrt(BeatHome*50), group = 'Home - Jun') %>%
# layer control
addLayersControl(
overlayGroups = c('Home - Jun'
),
options = layersControlOptions(collapsed = F)
) %>%
# legend for compare to average
addLegend('bottomright', pal = beatCol, values = last$BeatTotalLvl,
title = 'Compare<br>Quote Count to<br>3Mos State Avg',
opacity = 1)
m1
Here is the output.