Curved flow lines in leaflet minicharts R - r

I'm creating a flow map in R Leaflet which will eventually go through Shiny. This is a very simplified example of what it looks like:
How can I curve the flow lines?
Reproducible example:
library(leaflet)
library(leaflet.minicharts)
library(tidyverse)
dat <- data.frame(
Origin_lat = c(40.15212, 40.65027),
Origin_lng = c(-74.79037, -74.91990),
Dest_lat = c(40.78749, 40.78749),
Dest_lng = c(-73.96188, -73.96188),
flow = c(237, 84)
)
leaflet() %>%
addProviderTiles(providers$Esri.WorldGrayCanvas) %>%
setView(lat = 40.39650, lng = -74.39541, zoom = 9) %>%
addFlows(
lng0 = dat$Origin_lng,
lat0 = dat$Origin_lat,
lng1 = dat$Dest_lng,
lat1 = dat$Dest_lat,
flow = dat$flow
)

There is a package geosphere which has the functions which you need
This should get you where you need to be, you can pass it either a matrix for start and stop with X,Y in each or a vector for each type of coordinate, as here
library(geosphere) #install as needed
gcIntermediate(c(Origin_lat,Origin_lng), c(Dest_lat,Dest_lng),
n=80, #how many curve points along lines
addStartEnd=TRUE,
sp=TRUE ) %>%
leaflet() %>%
addTiles() %>%
addPolylines()
If it were me, I would restructure the points to be able to pass: origin & destination as two-column matrices of Lat, Lon values, but it should work as vectors too.

Related

Find the middle point between two markers in Leaflet

I would like to be able to find the centre point between two markers on a map (example below). Is there a function in leaflet or in another package that allows this? Thank you in advance
coor_zone6 <- c(3.16680, 3.16176, 42.46667, 42.46997)
matrice_coord_zone6 <- matrix(coor_zone6, nrow=2, ncol = 2)
colnames(matrice_coord_zone6) <- c("long", "lat")
matrice_coord_zone6 <- data.frame(matrice_coord_zone6)
matrice_coord_zone6$name <- c("M_1","M_3")
leaflet(matrice_coord_zone6) %>%
addMouseCoordinates(epsg = NULL, proj4string = NULL, native.crs = FALSE) %>%
addProviderTiles("Esri.WorldImagery") %>%
addMarkers(lng = ~long, lat = ~lat) %>%
addPolylines(~long, ~lat, popup = ~name)
I have not found any leaflet function that can perform this calculation, but it is not difficult to find the intermediate point between both coordinates.
You must add both longitudes and divide them by 2, you will have to do the same with both latitudes.
In your case, if I have not misunderstood, your first coordinate is (3.16680, 42.46667) and your second coordinate is (3.16176, 42.46997) so the calculation would be as follows:
(3,16680 + 3,16176) / 2 = 3,16428
(42,46667 + 42,46997) / 2 = 42,46832
So the intermediate point would be the following: (3.16428, 42.46832)

Adding images to maps with Leafpop

I'm trying to add separate images to popups so that as you click on each location, an image specific to that place/popup appears. I've figured out how to get one image in, but it applies to all of the popups on the map instead of just one. I have been trying to use the package leafpop for this, but I can't really figure out how to make it work. Even if I just use one image, nothing appears on the map.
This is what my code looks like for it:
library(leaflet)
library(leafpop)
img = system.file("file/image_name.jpg", package = "jpg")
leaflet(map) %>%
addTiles() %>%
addCircleMarkers(label = map#data$name,
weight = 2,
color = "grey",
fillColor = "red",
fillOpacity = 0.7)%>%
addPopupImages(img, group = "map")
I know there's some bits in there that I'm not quite doing right. At this point, I just want to know if it's even possible to do this the way I'm envisioning. Any help is appreciated.
The images need to be in a vector of the same length as the points passed to leaflet. Here is a reproducible example you can copy paste that will get you started:
library(tidyverse)
library(sf)
library(leaflet)
library(leafpop)
pts <- tibble(x = runif(10, 175, 176),
y = runif(10, -38, -37)) %>%
st_as_sf(coords = c("x", "y"), crs = 4326)
img <- glue::glue("https://github.com/IQAndreas/sample-images/blob/gh-pages/100-100-color/{11:20}.jpg?raw=true")
pts$img <- img
leaflet() %>%
addTiles() %>%
addCircleMarkers(data = pts, group = "pts") %>%
addPopupImages(pts$img, group = "pts")
Figured it out, with the help of Rich Pauloo! This is the code I ended up using the get local image files. It's a little clunky, but it worked out for me:
data_name <- readOGR("data/map_file.kml")
data_name2 <- data.frame(data_name)
pts <- st_as_sf(data.frame(data_name2),
coords = c("coords.x1", "coords.x2"), crs = 4326)
img <- c("images/picture_name.jpg") ##did this for every image I wanted to use, in the order
##that matched up with the data points I wanted them associated with.
pts$img <- img
leaflet() %>%
addTiles() %>%
addCircleMarkers(data = pts, group = "pts") %>%
addPopupImages(pts$img, group = "pts", width = 300)
Sorry if my conventions for writing out code are not quite right for the website. I just wanted to keep things generic and not include any of my file names or anything.

How to filter a raster layer and plot only the cells above a certain value in R using Leaflet?

I have a raster layer that contains 24-hour snow accumulations across the United States. The data can be pulled from here:
https://www.nohrsc.noaa.gov/snowfall_v2/data/202105/sfav2_CONUS_24h_2021052412.tif
I only want to plot the cells in the raster with values greater than or equal to 4 (inches) on a leaflet map. This is what my current map looks like:
https://i.stack.imgur.com/2Mi4r.png
I changed all values less than 4 to NA thinking that the raster cells wouldn't show up on the map. I want to remove all cells on the map that are greyed-out. The functions subset() and filter() do not work on raster layers. Any ideas? My code below for reference:
library(dplyr)
library(rgdal)
library(raster)
library(ncdf4)
library(leaflet)
library(leaflet.extras)
download.file(obsvSnow_Link, destfile = file.path(folderpath, 'observedSnow.tif'))
obsvSnow <- raster(file.path(folderpath, 'observedSnow.tif'))
names(obsvSnow) <- 'snowfall'
obsvSnow[obsvSnow < 4,] <- NA
colores <- c("transparent","#99CCFF","#3399FF","#0000FF","#FFE066", "#FF9900", "#E06666","#CC0000","#990033")
at <- c(4,8,seq(12,42,6),100)
cb <- colorBin(palette = colores, bins = at, domain = at)
mp <- leaflet(width = "100%",options = leafletOptions(zoomControl = FALSE)) %>%
addTiles() %>%
addRasterImage(x=obsvSnow$snowfall,
colors = cb,
opacity = 0.6) %>%
addLegend(title = 'Inches',
position='bottomright',
pal = cb, values = at) %>%
leaflet.extras::addSearchUSCensusBureau(options = searchOptions(autoCollapse=TRUE, minLength=10)) %>%
addScaleBar(position='bottomleft') %>%
addFullscreenControl()
mp

Cluster color in leaflet Heatmap

Is there a way how to have cluster colors in leaflets addHeatmap function, let say we have some values of variables and cluster them to 8 categories (see example), is there a way how to have also 8 color categories in the heatMap? I know this can be done in ggplot - geom_geom_tile
Is there a way ho to reproduce it in leaflet as well?
Example:
library(ggmap)
library(maptools)
library(ggplot2)
d = data.frame(
pred_res = runif(2000, -2, 2),
lat = runif(2000, 49.94, 50.18),
lon = runif(2000, 14.22, 14.71)
)
#top&bottom coding and discreting pred_res....8
d$res_coded<-replace(d$pred_res,d$pred_res<(-1),8)
d$res_coded<-replace(d$res_coded,d$pred_res>=-1,7)
d$res_coded<-replace(d$res_coded,d$pred_res>=-0.4,6)
d$res_coded<-replace(d$res_coded,d$pred_res>=-0.1,5)
d$res_coded<-replace(d$res_coded,d$pred_res>=0,4)
d$res_coded<-replace(d$res_coded,d$pred_res>=0.1,3)
d$res_coded<-replace(d$res_coded,d$pred_res>=0.4,2)
d$res_coded<-replace(d$res_coded,d$pred_res>=1,1)
d %>% head
d$res_coded %>% table
library(leaflet)
library(leaflet.extras)
leaflet() %>% addProviderTiles("CartoDB.Positron") %>%
addHeatmap(lng = d$lon, lat = d$lat, intensity = d$res_coded)
Please see the gradient function from the documentation here.
Here is an example with a different color palette:
leaflet() %>% addProviderTiles("CartoDB.Positron") %>%
addHeatmap(lng = d$lon, lat = d$lat, intensity = d$res_coded, gradient="RdYlGn")

Mapping Bus Routes with Leaflet in R

I recently found this shape file of NYC bus routes shape file of NYC bus routes (zip file) that I am interested in plotting with the leaflet package in R.
When I attempt to do so, some routes do not show up on the map. I can tell they're missing because I overlay the bus stop data and some do not line up with the routes.
When I read in the shape file, I notice that the spatial lines data frame that is created has nested lists, which I think leaflet is not mapping.
What do I need to do so that leaflet reads coordinates of these missing routes? Below is the code I used to produce the map with missing routes:
bus <- readOGR(dsn = path.expand("bus_route_shapefile"), layer = "bus_route_shapefile")
bus.pj <- spTransform(bus, CRS("+proj=longlat +datum=WGS84"))
bus.st <- readOGR(dsn = path.expand("bus_stop_shapefile"), layer = "bus_stop_shapefile")
bus.st.pj <- spTransform(bus.st, CRS("+proj=longlat +datum=WGS84"))
bus_map <- leaflet() %>%
setView(lng = -73.932667, lat = 40.717266, zoom = 11) %>%
addPolylines(data = bus.pj, color = "black", opacity = 1) %>%
addCircles(data=bus.st.pj#data,~stop_lon, ~stop_lat, color = "red") %>%
addTiles()
bus_map
It would be easier to help you if you provided not only bus_routes but also bus_stop (zip file). You can solve it by converting bus.pj into new SpatialLinesxxx obj where each class Lines has only one class Line. SLDF below code makes doesn't have bus.pj#data$trip_heads because of unknown.
library(dplyr); library(sp); library(leaflet)
## resolve bus.pj#lines into list(Line.objs) (Don't worry about warnings)
Line_list <- lapply(bus.pj#lines, getLinesLinesSlot) %>% unlist()
## If you want just Lines infromation, finish with this line.
SL <- sapply(1:length(Line_list), function(x) Lines(Line_list[[x]], ID = x)) %>%
SpatialLines()
## make new ids (originalID_nth)
ori_id <- getSLLinesIDSlots(bus.pj) # get original ids
LinLS <- sapply(bus.pj#lines, function(x) length(x#Lines)) # how many Line.obj does each Lines.obj has
new_id <- sapply(1:length(LinLS), function(x) paste0(x, "_", seq.int(LinLS[[x]]))) %>%
unlist()
## make a new data.frame (only route_id)
df <- data.frame(route_id = rep(bus.pj#data$route_id, times = LinLS))
rownames(df) <- new_id
## integrate Line.objs, ids and a data.frame into SpatialLinesDataFrame.obj
SLDF <- mapply(function(x, y) Lines(x, ID = y), x = Line_list, y = new_id) %>%
SpatialLines() %>% SpatialLinesDataFrame(data = df)
leaflet() %>%
setView(lng = -73.932667, lat = 40.717266, zoom = 11) %>%
addPolylines(data = SLDF, color = "black", opacity = 1, weight = 1) %>%
addCircles(data=bus.st.pj#data,~stop_lon, ~stop_lat, color = "red", weight = 0.3)

Resources