How to add multiple polygons in leaflet map using r loop? - r

I'm trying to add multiple polygon to leaflet world map, according to a number of lists of country code. And I was trying to use R loop to add the polygon. Here's the code that I manually add polygons from list 1:
library(sp)
library(raster)
library(leaflet)
library(maps)
library(tidyverse)
countries_1 <- c('PAK','TUR','BGR')
adm1 <- getData('GADM', country='PAK', level=0)
adm2 <- getData('GADM', country= 'TUR', level=0)
adm3 <- getData('GADM', country= 'BGR', level=0)
leaflet() %>%
addTiles() %>%
addPolygons(data=adm1, weight = 3, fillColor = 'purple', color = 'purple') %>%
addPolygons(data=adm2, weight = 3, fillColor = 'purple', color = 'purple') %>%
addPolygons(data=adm3, weight = 3, fillColor = 'purple', color = 'purple')
I am thinking using the loop to add multiple polygon layers so that for list_n:
countries_n <- ('ctry1','ctry2','ctry3',...'ctryn')
for (i in country_n) {
countries <- basemap %>% addPolygons(data=getData('GADM',country = i, level = 0),
weight = 3, fillColor = 'purple', color = 'purple')
}
The question is how can I embed the loop to "leflet() %>%" ?
*Note here:
If try to add multiple data in addPolygons(), it will plot only the first element in the data, in below case, only country 'PAK' will be ploted:
addPolygons(data=c('PAK','TUR'), weight = 3, fillColor = 'purple', color = 'purple')

Here's a solution using packages sf and mapview. Note that this is currently only possible using the develop version of mapview (see commented out devtools::install_github()
# devtools::install_github("r-spatial/mapview#develop")
library(sf)
library(mapview)
library(raster)
countries_1 <- c('PAK','TUR','BGR')
dat_list = lapply(countries_1, function(i) {
st_as_sf(getData("GADM", country = i, level = 0))
})
m = leaflet() %>% addTiles()
for (i in dat_list) {
m = mapview::addFeatures(map = m,
data = i,
weight = 3,
fillColor = 'purple',
color = 'purple')
}
m
Note that addFeatures is type agnostic, so any combination of points, lines and/or polygons will work here.

Related

How to set boundaries with leaflet and export to pdf with mapshot?

I have been trying for the whole day now to create a map an export it to a pdf. The problem is that I don't really understand how to either set "width" and "height" or use "fitBounds". Also I would like to crop this "Leaflet" logo at the bottom right. I tried to do a random reproducable example where I would like to only crop the blue rectangle. Any ideas?
remove(list = ls())
library(leaflet)
library(sf)
library(mapview)
### create random sf polygon
pol = st_sfc(st_polygon(list(cbind(c(0,3,3,0,0),c(0,0,3,3,0)))))
h = st_sf(r = 5, pol)
### create "map"
df <- leaflet(width = 1000, height = 1000) %>%
#fitBounds(100, 100, 100, 100) %>%
addPolygons(data = h,
color = "blue",
weight = 1,
opacity = 1,
fillOpacity = 1) %>%
setMapWidgetStyle(style = list(background = "transparent"))
### show map and export
df
mapshot(df, file = "leaflet.pdf")

Get longitude and latitude from a shapefile with Leaflet in R

I've been trying to map with leaflet to add addCircles() but my shapefile doesn't seem to have the latitude lat and longitude lng parameters so I got the centroids for each city as is the code below but it doesn't seem to show me the centroid points so I put in a df these values but I can't automate to get the points for n cities.
The data is here.
library(stringr)
library(leaflet)
library(sf)
library(dplyr)
quito = st_read("C:/Users/crist/Downloads/Administraciones Zonales/Administración_Zonal.shp") %>%
st_simplify(dTolerance = 1000) %>%
sf::st_transform('+init=epsg:4326')
sectores = read.csv("C:/Users/crist/Downloads/sector.csv", header = T,sep = ";", dec = ",", row.names = 1)
sectores
full_data = inner_join(quito, sectores, by = 'NOMBRE') %>%
mutate(label_map = sprintf("<strong>%s </strong><br/>Valor: %g<br/>",NOMBRE, TARIFA_PROMEDIO_POR_HAB_DISPONIBLE_...) %>% lapply(htmltools::HTML))
bins = c(0, 10, 50, 100, 150,250)
pal_quito <- colorBin("Oranges", domain = full_data$TARIFA_PROMEDIO_POR_HAB_OCUPADA_...,
bins = bins)
#I tried to do this because my shp didn't have the longitude and latitude variables
full_data$centroids <- st_transform(full_data, 29101) %>%
st_centroid() %>%
st_geometry()
lngt_q = c(-78.41782, -78.67333, -78.4823, -78.60407, -78.36822, -78.50851, -78.56278, -78.3023)
lat_q = c(-0.08668143, -0.2179538, -0.1585809, 0.09029626, -0.4124271, -0.2112893, -0.311081, -0.2025039)
full_data$lngt_q =lngt_q
full_data$lat_q =lat_q
leaflet(data = full_data) %>%
addTiles() %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addPolygons(data = full_data,
color = "#444444",
weight = 1,
smoothFactor = 0.5,
fillOpacity = 0.2,
label = full_data$label_map,
fillColor = pal_quito(full_data$TARIFA_PROMEDIO_POR_HAB_OCUPADA_...),
stroke = T,
highlightOptions = highlightOptions(
weight = 5,
color = "#666666",
fillOpacity = 0.7)) %>%
addCircles(full_data$centroids, lng = lngt_q, lat = lat_q, color = "#045a8d", weight = 1, radius =1500,
fillOpacity = 0.2)
[updated]
There's a way to get the longitude and latitude of my shapefile automatically.
I think you can do this by adding the centroid geometry to your polygon layer with st_centroid.
library(stringr)
library(leaflet)
library(sf)
library(dplyr)
library(mapview) # I believe this is needed to make code above function
quito = st_read("C:/Users/Brian/Downloads/Administraciones Zonales/Administración_Zonal.shp") %>%
st_simplify(dTolerance = 1000) %>%
#logintud y latitud # this produced an error, thin it is intended as comment
sf::st_transform('+init=epsg:4326')
## Adding the centroid of each polygon as a separate geometry column. This will not be active but can be accessed as needed
quito$geom2 = st_centroid(quito)
You will get a warning indicating that the centroids won't be accurate, because you are in a geographic rather than projected coordinate system and st_centroid assumes projected geometry. I would guess this isn't going to cause problems with reasonably small sized polygons at lower or middle latitudes, but you should be aware of the potential for distortion. If you need more accuracy, you could calculate your centroids before you warp into EPSG:4326 (WGS84). If you are going this route, you probably want to create the centroids as separate points, warp them separately and either join or use the separate points as your dataset to add the circles to your map.
At this point you can continue along the script as written until the last line, when you need to specify the geom2 column we created earlier as the data source
addCircles(data = full_data$geom2, fill = TRUE, stroke = TRUE, color = "#000", fillColor = "blue", radius = 800, weight = 1) ## I increased the radius to get it to display
I don't know best practices to share the leaflet here, but static image shown

AddLegend Display Value range instead of percentage when using colorQuantile

I am using R shiny-dashboard to display a weather raster file. I used colorQuantile as the method to display the color. In the legend, it shows the percentage. As you can see in the following image. I want the labels in the legend show the range of the value instead for each bin. I am not sure how to do that.
Here is my server.R
output$weather_map <- renderLeaflet({
rw = weatherband()
if (!is.null(rw)) {
pal_w = colorQuantile('RdYlGn', values(rw), na.color = 'transparent', n = 7)
leaflet() %>%
addTiles() %>%
addRasterImage(rw, colors = pal_w, opacity = 0.5) %>%
addLegend(position = 'topright', pal = pal_w, value = raster::values(rw), opacity = 1)
}
})
Note: rw is the raster image.
Thank you in advance!!
When I need want to adjust the labels in leaflet I fall back to using the arguments colors and labels instead of pal and values. The upside is you can customize the downside is a few more lines of code.
Since I don't have access to rw I'm grabbing my favorite map example:
library(sf)
nc <- st_read(system.file("shape/nc.shp", package="sf"))
Then the leaflet alternative pattern for customizing the legend labels:
library(leaflet)
qpal <- colorQuantile("RdYlBu", nc$AREA, n = 5)
# the extra code building off the existing pal
qpal_colors <- unique(qpal(sort(nc$AREA))) # hex codes
qpal_labs <- quantile(nc$AREA, seq(0, 1, .2)) # depends on n from pal
qpal_labs <- paste(lag(qpal_labs), qpal_labs, sep = " - ")[-1] # first lag is NA
map %>%
addPolygons(stroke = FALSE, smoothFactor = 0.2, fillOpacity = 1,
color = ~qpal(AREA)
) %>%
addLegend(colors = qpal_colors, labels = qpal_labs, opacity = 1)

Missing polygons while using Leaflet in R

I'm trying to reproduce a code to display polygons in a map in another computer, however, in one computer the polygons are not shown. Does someone had this kind of problem while sharing code?
You can download the shapefile from here: http://www.conabio.gob.mx/informacion/metadata/gis/muni_2012gw.xml?_xsl=/db/metadata/xsl/fgdc_html.xsl&_indent=no
library(rgdal)
library(rgeos)
library(leaflet)
Mex <- readOGR(dsn="C:/DISCO D", layer="Muni_2012gw")
Mex_sub <- Mex[Mex$CVE_ENT=="01",]
bins <- quantile(Mex_sub#data$OID_1, c(0,.125,.25, .5, .75,.875, 1))
pal <- colorBin("YlOrRd", domain = Mex_sub#data$OID_1, bins = (bins),
na.color = "grey40", reverse = FALSE)
centr <- gCentroid(Mex_sub)#coords
leaflet(Mex_sub, options = leafletOptions(minZoom = 4, maxZoom = 15)) %>%
addTiles() %>%
setView(centr[1], centr[2], zoom = 8) %>%
addPolygons(data=Mex_sub, weight = 1,fill = ~OID_1, fillColor = ~pal(OID_1),
opacity=1, fillOpacity = 0.5, color=grey(0.5))

How to "addTiles" on top of "addPolygons" in R's Leaflet?

How do you set the layer order in R's leaflet package so that tiles show up on top of polygons filled with color?
Here's what I've got so far:
require(leaflet)
require(acs)
require(tigris)
require(rgdal)
census.income.end.year = 2015
county = 17
nd.counties=acs.fetch(geography=geo.make(state="ND", county=county),
table.number="B01003", endyear = 2015)
tracts <- tigris::tracts(state = 'ND', county = county, cb=FALSE, year = 2015)
# create a geographic set to grab tabular data (acs)
geo<-geo.make(state=c("ND"),
county = county,
tract="*")
# add in median income
median.income <- acs.fetch(endyear = census.income.end.year,
geography = geo,
variable = c("B19013_001"))
income_df <- data.frame(paste0(as.character(median.income#geography$state),
str_pad(as.character(median.income#geography$county), 3, 'left', '0'),
str_pad(as.character(median.income#geography$tract), 5, 'left', '0')),
median.income#estimate)
rownames(income_df)<-1:nrow(income_df)
names(income_df)<-c("GEOID", "hhincome")
income_merged <- geo_join(tracts, income_df, "GEOID", "GEOID")
income_merged <- spTransform(income_merged, CRS("+init=epsg:4326"))
qpal <- colorQuantile("plasma", income_df$hhincome, n = 4)
leaflet() %>%
setView( -96.7898, 46.8772, zoom=11) %>%
addPolygons(data = income_merged,
fillColor = qpal(income_merged$hhincome),
fillOpacity = 1,
weight = 0.3) %>%
addProviderTiles(providers$Hydda.RoadsAndLabels)
Ultimately, I'ld like to do this with addTiles (instead of addProviderTiles as in the above code) using a custom MapBox, but I can't figure out how to make that reproducible for this example... given that you need a key to access custom MapBox tiles (BTW, I've created a custom MapBox tile that should be transparent except for roads and labels, so the underlying polygons should "show thru.")
Here is one way to do add a tile on top of a circle with the non-R version of leaflet: http://jsfiddle.net/dcu9pz2w/, but I don't see how to make that work in my context. I think adding "panes" may be the way to go, but I don't see that functionality in R leaflet. Also, I explored z-index values, but that seemed to be a dead end.
Any help is much appreciated!
R leaflet now includes addMapPane function. The solution to this problem is to first set up pane order and then add tiles/polygons. Reproducible example:
library(leaflet)
library(geojsonio)
# get polygon data
# https://github.com/simonepri/geo-maps/blob/master/info/countries-land.md
world <- geojson_read(
"https://github.com/simonepri/geo-maps/releases/download/v0.6.0/countries-land-10km.geo.json",
what = "sp"
)
# generate random values
world#data$value <- runif(nrow(world#data))
# get color palette
color_pal <- colorNumeric(palette = "YlOrRd", domain = NULL)
# get leaflet map
leaflet() %>%
setView(lat = 50, lng = 15, zoom = 4) %>%
addMapPane("background_map", zIndex = 410) %>% # Level 1: bottom
addMapPane("polygons", zIndex = 420) %>% # Level 2: middle
addMapPane("labels", zIndex = 430) %>% # Level 3: top
addProviderTiles(
providers$Esri.WorldTerrain,
options = pathOptions(pane = "background_map")
) %>%
addPolygons(
data = world, stroke = FALSE, smoothFactor = 0.2,
fillOpacity = 0.6, fillColor = ~color_pal(value),
options = pathOptions(pane = "polygons")
) %>%
addProviderTiles(
providers$Stamen.TonerLabels,
options = pathOptions(pane = "labels")
)

Resources