How to bind csv-data to geojson with Leaflet in R - r

In R (shiny) I'm using Leaflet. I want to use a geojson file with polygons; each polygon has an id. I also want to use a csv-file with measurements for every id in the geojson.
My question is: Do I have to merge these files first before I can use them with leaflet or can I use the data from the csv separately in leaflet?
And if I have to merge them first, how do I merge these files and keep the polygons in the result, because if I use the function merge, the result will not be a SpatialPlolygonsDataframe.
My code
library(viridis)
library(geojsonio)
library(leaflet)
setwd('H:/Mijn documenten/R')
Neighborhoods <- geojsonio::geojson_read("Buurten/BuurtGrHTB2017_2.geojson",
what = "sp")
deData <- read.csv(file="Buurten/Gegevens.csv", header=TRUE, sep=";")
MapData <- merge(Neighborhoods,deData,by='BU_CODE')
pal <- colorNumeric("viridis", domain = NULL, reverse=TRUE)
leaflet(MapData) %>%
addTiles() %>%
addPolygons(stroke = FALSE, smoothFactor = 0.3, fillOpacity = 1, fillColor=~pal(ifelse(P_GEHUWD<0,NaN,P_GEHUWD))) %>%
addLegend(pal = pal, values = ~(ifelse(P_GEHUWD<0,NaN,P_GEHUWD)), title="Aantal Inwoners", opacity = 1.0)

I recommend using the sf-package. It's the latest generation of spatial data manipulation in R and easier to handle.
library(sf)
library(tidyverse)
library(geojsonsf)
Neighborhoods <- geojson_sf('H:/Mijn documenten/R/Buurten/BuurtGrHTB2017_2.geojson')
deData <- read.csv(file='H:/Mijn documenten/R/Buurten/Gegevens.csv', header=TRUE, sep=";")
inner_join(Neighbourhoods, deData, by = 'BU_CODE') -> MapData
or without dplyr
MapData <- merge(Neighbourhoods, deData, by = 'BU_CODE')
From there you are able to do whatever you want with leaflet

Related

can we popop the name of the place when we use addGeoJson in R

I'm using addgeoJson function for the india map. I have data that I got it from here
https://gadm.org/download_country.html
for example I'm using this data
This is a json file and I read that json file and pass it to addGeoJson function.
library(jsonlite)
library(leaflet)
url <- "https://raw.githubusercontent.com/openseattle/seattle-boundaries/master/data/zip-codes.geojson"
geojson <- fromJSON(url, simplifyVector = FALSE)
leaflet() %>%
addTiles() %>%
addGeoJSON(geojson) %>%
setView(lng = -122.2, lat = 47.6, zoom = 10)
So I need to popup the names when I click on a particular state or city here. It should give some information when we click on it.
Is this possible to do it? and how?
The information you are looking for is stored deep in the structure of a geojson file (list). See for instance the first object of your dataset
geojson$features[[1]]$properties
Luckily there is a easier way to deal with it.
Use the package leaflet.extra, function addGeoJSONv2 specifying your label under argument popupProperty
library(leaflet.extras)
library(jsonlite)
library(leaflet)
url <- "https://raw.githubusercontent.com/openseattle/seattle-
boundaries/master/data/zip-codes.geojson"
geojson_fil <- fromJSON(url, simplifyVector = FALSE)
leaflet() %>%
addTiles() %>%
setView(lng = -122.2, lat = 47.6, zoom = 10) %>%
addGeoJSONv2(geojson_fil,
popupProperty = 'ZCTA5CE10')

How to create dynamic leaflet plot by using selectinput variable selection on reactive data in r shiny?

I am running a leaflet plot in shiny that is already partially dynamic with selection to create reactive data but having troubles in dynamic variable selection on reactive data in renderLeaflet({}) section.
looking to dynamically change: district_map_data()$Daily_confirmed with district_map_data()$input$id_districts_var_selection.
Working code below when variable is fixed to (Daily_confirmed):
district_map_data <- reactive({
req(input$id_state_for_district)
district_map_data <- state_level_map %>%
data preprocessing code ...
}) %>%
bindCache(input$id_state_for_district)
# ------------------------------------------------------------------ #
output$id_state_map <- renderLeaflet({
req(input$id_districts_var_selection)
pal_district <- colorBin(palette = "plasma", bins = 4,
# Need dynamic code here
domain = district_map_data()$Daily_confirmed) # {input$id_districts_var_selection}
label_district = paste("Latest Daily Cases:",
# Need dynamic code here
as.character(district_map_data()$Daily_confirmed)) %>%
lapply(htmltools::HTML)
district_map_data() %>% leaflet() %>%
addPolygons(
label = label_district,
# Need dynamic code here
fillColor = ~ pal_district(Daily_confirmed)) %>%
addLegend(position = "bottomleft",
pal = pal_district,
# Need dynamic code here
values = ~ district_map_data()$Daily_confirmed,
opacity = 0.7)
})
One possible way I know is to pivot longer the variables into 1 & filter it within the reactive data itself with the selectInput selection but will only try that if I do not find any solution here.
Any help is much appreciated !!!

Extracting data from a WMS-layer

I am trying to extract data from a WMS-layer.
As an example, I would like to analyse whether or not a Natura2000 area is touched by my area and what the specifics are of the Natura2000 area.
The WMS-layer of the Natura2000 area can be found at:
https://geodata.nationaalgeoregister.nl/natura2000/ows?service=WMS&request=GetLegendGraphic&format=image/png&width=20&height=20&layer=natura2000"
Let's say my area is a circle with a radius of 7500 meters around a certain x- and y-coordinate;
I was trying to get this done with the leaflet-package, but it seems more a tool to show information, instead of analysing information.
x.WGS=6.662226
y.WGS=52.53206
leaflet() %>% setView(x.WGS, y.WGS, zoom = 11) %>%
addTiles() %>%
addMarkers(lng = x.WGS, lat = y.WGS)%>%
addWMSTiles(
"https://geodata.nationaalgeoregister.nl/natura2000/ows?service=WMS&request=GetLegendGraphic&format=image/png&width=20&height=20&layer=natura2000",
layers = "natura2000",
options = WMSTileOptions(format = "image/png", transparent = TRUE),
attribution = "") %>%
addCircles(lng = x.WGS, lat = y.WGS, weight = 1,
radius = 7500)
I would like it to return two things. Is any Natura2000-area touched by my area? and which areas are that, in other words, what are their names. If I load the WMS-layer in Qgis the name of an Natura2000-area should be under naam_n2k.
In my example, the answer should be that there are two Natura2000 area's touched by my area and the names of these Natrua2000 area's are Vecht- en Beneden-Reggegebied and Engbertsdijksvenen.
The leaflet package is a R package to access leaflet functionality,
one of the most popular open-source JavaScript libraries for displaying interactive maps. More info: https://rstudio.github.io/leaflet/
As #IvanSanchez notes, a Web Map Service (WMS) is a map that you can load in your own application. See this as a georeferenced image/picture without information about the actual polygons, shapes etc.
If you want to do some analysis with polygons or retrieve information, you might need a Web Feature Service (WFS).
First of all, this is the code to load the WMS correctly.
# corrected WMS version
library(leaflet)
library(leaflet.extras) # for WMS legend
x.WGS=6.662226
y.WGS=52.53206
leaflet() %>% setView(x.WGS, y.WGS, zoom = 11) %>%
addTiles() %>%
addMarkers(lng = x.WGS, lat = y.WGS)%>%
addWMSTiles(
baseUrl = "https://geodata.nationaalgeoregister.nl/natura2000/ows?service=WMS",
layers = "natura2000",
options = WMSTileOptions(format = "image/png", transparent = TRUE),
attribution = "") %>%
addCircles(lng = x.WGS, lat = y.WGS, weight = 1,
radius = 7500) %>%
addWMSLegend(uri ="https://geodata.nationaalgeoregister.nl/natura2000/ows?service=WMS&request=GetLegendGraphic&format=image%2Fpng&width=20&height=20&layer=natura2000")
Secondly, to answer your question: we can add a CQL query with a geometry filter to a WFS request.
Note that this is possible in your specific case, but this is not standard for all WFS services.
# Since you want to do spatial analysis on features, we load the sf package
# more info: https://r-spatial.github.io/sf/
library(sf)
# we convert your point coordinates to the native CRS of the WFS layer:
# make point and assign WGS84 CRS
x <- st_point(c(x.WGS,y.WGS))
x <- st_sfc(x) %>% st_set_crs(NA) %>% st_set_crs(4326)
# transform to EPSG::28992 // Amersfoort RD is default CRS for the wfs layer
x_RD <- st_transform(x,28992)
# The WFS allows spatial filtering (this is not always the case)
# so you can use a cql filter with a distance around your point:
# cql_filter=dwithin(natura2000:geom,point(241514 505696.5),7500,meters)
# combining and encoding the cql filter for a valid WFS url:
WFS_url <- paste0("http://geodata.nationaalgeoregister.nl/natura2000/wfs?",
"&service=wfs&version=2.0.0&request=GetFeature&",
"typeName=natura2000:natura2000&cql_filter=",
URLencode(
paste0("dwithin(natura2000:geom,",
st_as_text(x_RD),
",7500, meters)"),
reserved = FALSE),
"&outputFormat=application/json"
)
# get WFS feature
natura2000 <- st_read(WFS_url)
# Transform to WGS84
natura2000_wgs84 <- st_transform(natura2000,4326)
# load data in leaflet
leaflet() %>%
addTiles() %>%
addMarkers(lng = x.WGS, lat = y.WGS) %>%
addCircles(lng = x.WGS, lat = y.WGS, weight = 1,
radius = 7500) %>%
addPolygons(data = natura2000_wgs84,
label = ~naam_n2k,
popup = ~naam_n2k)

Multi-Point Select in R/Shiny/Leaflet

I have a map that I generate using Leaflet in an R/Shiny app, and am able to listen to event clicks on points on the map using code like this
observeEvent(input$map_marker_click, {
p = input$map_marker_click
p1 = filteredData()[filteredData()$Longitude == p$lng & filteredData()$Latitude == p$lat),]
if(p$id != 'Selected') {
//do stuff
}
output$ggplot = renderPlot({
//change plot based on selected point
})
}
But I'm wondering if it's possible to allow a user to select multiple points at once -- perhaps by shift-select or some other way. Would I need to somehow add a listener to see if they are holding down SHIFT, and then pass along a vector of clicked points?
EDIT:
I found an example that shows how to use MapEdit with selectFeatures to multi-select points on a leaflet map and then "do something" with the selection.
Here's the code sample along (taken from: https://gis.stackexchange.com/questions/253483/leaflet-tool-for-multiple-marker-selection-and-computation-of-summary)...:
# devtools::install_github("r-spatial/mapedit")
library(sf) # for spatial data type representation
library(mapview) # for the raster data and quick viewing
library(mapedit) # for the interaction (selection of the data)
# create the base map with a raster layer
m = mapview(poppendorf[[5]])
# create some mock data points in the vicinity of the raster layer
set.seed(42) # to be reproducible
dframe = data.frame(a = 1:50,
b = rnorm(50, 2, 1),
x = runif(50, 11.15, 11.25),
y = runif(50, 49.7, 49.75))
# convert data.frame to sf object as we need
# geo-spatial data type for this kind of objective
# epsg 4326 is geographic longlat 'projection'
dframe_sf = st_as_sf(dframe, coords = c("x", "y"), crs = 4326)
# inspect data on base map
mapview(dframe_sf, map = m)
# select features via polygon/rectangle/line/point or the like
# by using the draw tools of the draw toolbar on the left
# and press "Done" when finished.
# multiple selections are also possible.
# (line/point selection will not work as points have no dimension!)
# mode = "click" will enable selection via clicking on features.
selected = selectFeatures(dframe_sf, map = m, mode = "draw")
# check the selection (selected will be diplayed in blue)
mapview(dframe_sf, map = m, col.regions = "red") + selected
# given that selected is a sf object (and hence a data.frame)
# claculating summaries works just as expected with a normal data.frame
summary(selected)
mean(selected$a)
mean(selected$b)
sd(selected$b)
# we can also set other selection criteria. e.g. invert selection via st_disjoint
diff_selected = selectFeatures(dframe_sf, map = m, mode = "draw", op = st_disjoint)
# check the selection (selected will be diplayed in blue)
mapview(dframe_sf, map = m, col.regions = "red") + diff_selected
I understand that the following line is responsible for taking the SF dataframe and allowing us to select points on the map:
selected = selectFeatures(dframe_sf, map = m, mode = "draw")
My question is this -- how do I get it to render that same view but in Shiny, as opposed to my R console?
In Shiny, we have to wrap the leaflet map in the renderLeaflet function...
If I were doing it without Shiny, I could just do something like this:
m = leaflet(data = df) %>%
addCircleMarkers() %>%
addLegend...
selected = selectFeatures(dframe_benthic_sf, map = m, mode = "click")

How to display multiple polygons at once using leaflet addGeoJSON() function?

I am trying to display several zipcodes (thus polygons...) on a leaflet map. Data is available as a geojson file here. I chose as an example some zip codes from Seattle.
I tried the following (reproducible example):
library(jsonlite)
library(leaflet)
url <- "https://raw.githubusercontent.com/openseattle/seattle-boundaries/master/data/zip-codes.geojson"
geojson <- fromJSON(url)
map <- leaflet() %>% addTiles() %>% addGeoJSON(geojson)
map
I could not figure out how to properly set addGeoJSON parameters, and calling map only displays the leaflet() %>% addTiles() part...
Documentation is too light for the non json advanced user that I am:
geojson: a GeoJSON list, or character vector of length 1
How should I proceed? Thank you very much in advance for your views on this issue
Regards
You just needed to not parse the geojson to a data.frame, fromJSON(url, FALSE)
library(jsonlite)
library(leaflet)
url <- "https://raw.githubusercontent.com/openseattle/seattle-boundaries/master/data/zip-codes.geojson"
geojson <- fromJSON(url, simplifyVector = FALSE)
leaflet() %>%
addTiles() %>%
addGeoJSON(geojson) %>%
setView(lng = -122.2, lat = 47.6, zoom = 10)
addGeoJSON() will also accept a string, e.g.
geojson_str <- paste0(readLines(url), collapse = "")
then pass that to addGeoJSON

Resources