R Leaflet not mapping polylines to datarame - r

I use Leaflet with R quite frequently, but I've not used addPolylines before.
I have a series of lines with origin and destination locations that I'm attempting to plot on a map, and I'm noticing some weird behaviour:
Polylines and markers mapped to the same dataframe are not appearing in the same location.
Labels are not mapping at all to the dataframe, instead only returning the values in the last row for all lines.
Line weight mapping is not working.
I'm not entirely sure what I'm doing wrong here - any help would be appreciated. I've included a reproducible example below.
dummy <- data.frame(
Line_name = c("line1", "line2", "line3"),
origin_lng = c(145.1234, 147.223, 153.225),
origin_lat = c(-17, -19.4, -27.6),
Destination_lng = c(147.223, 153.225, 156.1123),
Destination_lat = c(-19.4, -27.6, -30.5),
Line_weight = c(1, 2, 5)
)
leaflet() %>%
addProviderTiles(provider = providers$Esri.WorldImagery) %>%
setView(lng = 146.612020, lat = -21.628836, zoom = 5) %>%
addMarkers(lng = dummy$origin_lng, lat = dummy$origin_lat, label = "origins") %>%
addPolylines(
lng = c(dummy$origin_lng, dummy$Destination_lng),
lat = c(dummy$Origin_lat, dummy$Destination_lat),
weight = dummy$Line_weight,
label = paste0(
"Line name: ", dummy$Line_name, "<br>",
"Origin coords: ", dummy$origin_lng, " ", dummy$origin_lat, "<br>",
"Destination coords: ", dummy$Destination_lng, " ", dummy$Destination_lat
) %>% lapply(htmltools::HTML)
)

You have to group the lines. You used the columns of dummy as independent vectors but sent no groups. Leaflet doesn't 'know' which labels go with which line segments. Additionally, you did get a popup, but you have to hover. (You only had one, as well.)
So, in short—grouping the data... There is probably an easier way of doing this, but this works. I pivoted longer to going the lat/long. Then I pivoted wider. Essentially, I needed the longs in a column and the lats in a column.
library(leaflet)
library(tidyverse)
dum2 <- dummy %>% pivot_longer(cols = names(.)[2:5], names_to = c("ft", "val"),
names_sep = "_", values_to = "lng_lat") %>%
pivot_wider(id_cols = c("Line_name", "ft", "Line_weight"),
names_from = "val", values_from = "lng_lat")
Then I separated the call for addPolyLines. You need one call for each group.
mp <- leaflet() %>%
addProviderTiles(provider = providers$Esri.WorldImagery) %>%
setView(lng = 146.612020, lat = -21.628836, zoom = 5) %>%
addMarkers(lng = dummy$origin_lng, lat = dummy$origin_lat, label = "origins")
map(dummy$Line_name,
function(group){
mp <<- addPolylines(
mp,
data = dum2[dum2$Line_name == group, ],
lng = ~lng,
lat = ~lat,
weight = ~Line_weight,
labelOptions = list(noHide = T, sticky = T, permanent = T),
label = paste0(
"Line name: ", group, "<br>",
"Origin coords: ", dummy[dummy$Line_name == group, ]$origin_lng,
" ", dummy[dummy$Line_name == group, ]$origin_lat, "<br>",
"Destination coords: ", dummy[dummy$Line_name == group, ]$Destination_lng,
" ", dummy[dummy$Line_name == group, ]$Destination_lat) %>%
lapply(htmltools::HTML))
}
)

Related

R Displaying Points Twice?

I have this code for an interactive map in R:
library(leaflet)
library(inlmisc)
Long = rnorm(1000, -71, 0.5)
Lat = rnorm(1000, 42.3, 0.5)
loc = rep("loc", 1000)
Name = rep("Location", 1000)
num = 1:1000
Label = paste0(loc, "_", num)
Location = paste0(Name, "_", num)
df = data.frame(Name, Lat, Long, Label)
map <- leaflet(df) %>% addProviderTiles(providers$OpenStreetMap) %>%
addMarkers( clusterOptions = markerClusterOptions(), popup = ~paste("title: ", Name)) %>%
addTiles() %>%
setView(lng=-71.0589,lat=42.3301, zoom=12) %>%
addMarkers(~Long, ~Lat, popup = ~Name, group="marker", label = ~Label) %>%
inlmisc::AddSearchButton(group = "marker", zoom = 15,
textPlaceholder = "Search here")
The map seems to work fine - but the "icons" are being displayed twice (i.e. blue pins and colored circles, e.g. yellow, green):
Is there a way to have it such that when you zoom out, the blue pins collapse into the colorful circles - and when you zoom in, the colorful circles collapse into the blue pins?
Thank you!
It looks like you are adding the markers twice.
The first addMarkers line, does the clustering with zoom that it sound like you are interested in.
You can add the group and label options to the first addMarkers call, to be able to search and have mouse-over labels as well as the clustering.
map <- leaflet(df) %>% addProviderTiles(providers$OpenStreetMap) %>%
addMarkers( clusterOptions = markerClusterOptions(),
popup = ~paste("title: ", Name),
group="marker", label = ~Label) %>%
addTiles() %>%
setView(lng=-71.0589,lat=42.3301, zoom=12) %>%
inlmisc::AddSearchButton(group = "marker", zoom = 15,
textPlaceholder = "Search here")
Using the answer of #Senithil913 - I added a reset option:
map <- leaflet(df) %>% addProviderTiles(providers$OpenStreetMap) %>%
addMarkers( clusterOptions = markerClusterOptions(),
popup = ~paste("title: ", Name),
group="marker", label = ~Label) %>%
addTiles() %>%
setView(lng=-71.0589,lat=42.3301, zoom=12) %>%
inlmisc::AddSearchButton(group = "marker", zoom = 15,
textPlaceholder = "Search here") %>% addResetMapButton()

Showing two labels over a polygon in leaflet in R

I am mapping out zip code areas in leaflet and coloring the polygon based on the Dealer.
Dealer Zipcodes geometry
A 32505 list(list(c(.....)))
B 32505 ....
This code is used to create the colors, labels, and the map.
factpal <- colorFactor(topo.colors(5), data$Dealer)
labels <- paste0("Zip Code: ",data$Zipcodes, ", Dealer: ", data$Dealer)
leaflet(data) %>%
addTiles() %>%
addPolygons( color = ~factpal(Dealer),),
label = labels) %>%
leaflet.extras::addSearchOSM(options = searchOptions(collapsed = FALSE)) %>%
addLegend(pal = factpal, values = ~Dealer,
opacity = 0.7,
position = "bottomright")
When the zip code (and thus the geometry) are the same between two dealers, only one label is visible, though it is clear colors are overlapping. All I want is for that label to somehow show the info for both dealers in that zip code. Please let me know if there is code missing you need, or clarification needed.
Not sure whether you could have multiple tooltips but to show all Dealers in the tooltip you could change your labels such that they include all dealer names per zip code, e.g. making use of dplyr you could do:
library(leaflet)
library(dplyr)
factpal <- colorFactor(topo.colors(5), data$Dealer)
data <- data %>%
group_by(Zipcodes) %>%
mutate(labels = paste(Dealer, collapse = ", "),
labels = paste0("Zip Code: ", Zipcodes, ", Dealer: ", labels))
leaflet(data) %>%
addTiles() %>%
addPolygons(
color = ~factpal(Dealer),
label = ~labels,
weight = 1
) %>%
# leaflet.extras::addSearchOSM(options = searchOptions(collapsed = FALSE)) %>%
addLegend(
pal = factpal, values = ~Dealer,
opacity = 0.7,
position = "bottomright"
)
DATA
nycounties <- rgdal::readOGR("https://eric.clst.org/assets/wiki/uploads/Stuff/gz_2010_us_050_00_20m.json")
nycounties_sf <- sf::st_as_sf(nycounties)
nycounties_sf_n <- nycounties_sf %>%
filter(STATE == "01") %>%
select(Zipcodes = COUNTY, geometry)
data <- list(
A = sample_n(nycounties_sf_n, 40),
B = sample_n(nycounties_sf_n, 40),
C = sample_n(nycounties_sf_n, 40),
D = sample_n(nycounties_sf_n, 40)
)
data <- purrr::imap(data, ~ mutate(.x, Dealer = .y))
data <- do.call("rbind", data)

I want to know how to print multiple columns of addcircles(popup=...) in R using leaflet package

here is my R code
library(leaflet)
m <- leaflet() %>%
addTiles() %>%
setView(lng = 126.97806, lat=37.56667, zoom=16)
m
acci <- read.csv("C:/accidents.csv")
acci
leaflet(acci) %>%
setView(lng = 126.97806, lat=37.56667, zoom=13) %>%
addTiles() %>%
addCircles(lng=~longitude, lat=~latitude, color=~acci_colour(accidenttype), popup=~accidentplace) %>%
addLegend(position = "bottomleft",
title = "accidenttype",
pal = acci_colour, values = ~accidenttype, opacity = 1)
acci_colour <- colorFactor("viridis", acci$accidenttype)
SO, I want to know how to get multiple informations of data acci when i click the circle mark on the leaflet map.
I tried :
addCircles(lng=~longitude, lat=~latitude, color=~acci_colour(accidenttype), popup=~accidentplace, ~...., ~.....)
addCircles(lng=~longitude, lat=~latitude, color=~acci_colour(accidenttype),popup=paste(acci$accidentplace, acci$..., acci$...)
addCircles(lng=~longitude, lat=~latitude, color=~acci_colour(accidenttype), popup=colnames(acci)[5:9])
... Thank you
You only need to use ~ once and paste the column data together using html for formatting.
For example:
Data for reprex
library(leaflet)
df <- data.frame(
lat = runif(10, 35, 40),
lon = runif(10, 80, 120),
n = 1:10,
txt1 = sample(LETTERS, 10),
txt2 = sample(letters, 10)
)
Example 1
leaflet(df) %>%
addTiles() %>%
addCircles(
lng = ~lon,
lat = ~lat,
popup = ~paste(n, txt1, txt2, sep = "<br>")
)
Example 2 (more control)
library(htmltools)
leaflet(df) %>%
addTiles() %>%
addCircles(
lng = ~lon,
lat = ~lat,
popup = ~paste0(
"<b>n: ", n, "</b><br>",
"id1: ", txt1, "<br>",
"id2: ", txt2, "<br>"
)
)
Using htmltools::htmlEscape() ensures the column text isn't interpreted as html. It's not strictly necessary for this example.

Plotly animated map not showing countries with NA values

I posted this in the plotly community forum but got absolutely no activity! Hope you can help here:
I have map time-series data, some countries don’t have data and plotly does not plot them at all. I can have them outlined and they look different but it appears nowhere that the data is missing there (i.e. I want a legend entry). How can I achieve this? Here is a reprex:
library(plotly)
library(dplyr)
data = read.csv('https://github.com/lc5415/COVID19/raw/master/data.csv')
l <- list(color = toRGB("grey"), width = 0.5)
g <- list(
scope = 'world',
countrycolor = toRGB('grey'),
showframe = T,
showcoastlines = TRUE,
projection = list(type = 'natural earth')
)
map.time = data %>%
plot_geo() %>%
add_trace(z = ~Confirmed, color = ~Confirmed, frame = ~Date, colors = 'Blues',
text = ~Country, locations = ~Alpha.3.code, marker = list(line = l)) %>%
colorbar(title = 'Confirmed') %>%
layout(
title = 'Number of confirmed cases over time',
geo = g
) %>%
animation_opts(redraw = F) %>%
animation_slider(
currentvalue = list(
prefix = paste0("Days from ",
format(StartDate, "%B %dnd"),": "))) %>%
plotly_build()
map.time
Note that the countries with missing data (e.g. Russia) have as many data points as all other countries, the issue is not that they do not appear in the dtaframe passed to plotly.
The obvious way to handle this is to create a separate labels column for the tooltip that reads "No data" for NA values (with the actual value otherwise), then make your actual NA values 0. This will give a uniform appearance to all the countries but correctly tells you when a country has no data.
map.time = data %>%
mutate_if(is.numeric, function(x) {x[is.na(x)] <- -1; x}) %>%
plot_geo() %>%
add_trace(z = ~Confirmed, color = ~Confirmed, frame = ~Date, colors = 'Blues',
text = ~Country, locations = ~Alpha.3.code,
marker = list(line = l)) %>%
colorbar(title = 'Confirmed') %>%
layout(
title = 'Number of confirmed cases over time',
geo = g
) %>%
animation_opts(redraw = F) %>%
animation_slider(
currentvalue = list(
prefix = paste0("Days from ",
format(StartDate, "%B %dnd"),": "))) %>%
plotly_build()
Which gives:

Exchanging map results using leaflet and state_popup

I have a database of medical consultations by cities. I use the leaflet and state_popup function to display the results on a map, as described below:
pal <- colorBin("Blues",domain = DATA$QUANTITY_MEDICAL,bins = c(1, 1000, 5000, 10000, 50000,100000,300000),na.color=NA)
state_popup <- paste0("<strong>CITY: </strong>",
DATA$CITY,
"<br><strong> QUANTITY OF MEDICAL CONSULTATION: </strong>",
DATA$QUANTITY_MEDICAL)
leaflet(data = DATA) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(fillColor = ~pal(QUANTITY_MEDICAL),
fillOpacity = 0.7,
color = "#BDBDC3",
weight = 1,
popup = state_popup) %>%
addLegend("topright","bottomright", pal = pal, values = ~ DATA$QUANTITY_MEDICAL,
title = " QUANTITY OF MEDICAL CONSULTATION ",
opacity = 1)
This script only shows one result at a time (medical consultations). I would like to include information about other medical procedures that I want to include, such as exams or hospitalizations.
I want for each procedure (medical consultation, exams or hospitalization) to include a button that would change the result. In my database (DATA) I already have the columns that separate the procedures I quoted. Is it possible to include this button to change the results on the map?
You are going to have to define groups it seems to me. There is a good link from RStudio on leaflet that may help you.
https://rstudio.github.io/leaflet/showhide.html
Here is some sample code from that site:
quakes <- quakes %>%
dplyr::mutate(mag.level = cut(mag,c(3,4,5,6),
labels = c('>3 & <=4', '>4 & <=5', '>5 & <=6')))
quakes.df <- split(quakes, quakes$mag.level)
l <- leaflet() %>% addTiles()
names(quakes.df) %>%
purrr::walk( function(df) {
l <<- l %>%
addMarkers(data=quakes.df[[df]],
lng=~long, lat=~lat,
label=~as.character(mag),
popup=~as.character(mag),
group = df,
clusterOptions = markerClusterOptions(removeOutsideVisibleBounds = F),
labelOptions = labelOptions(noHide = F,
direction = 'auto'))
})
l %>%
addLayersControl(
overlayGroups = names(quakes.df),
options = layersControlOptions(collapsed = FALSE)
)
I have a map I update monthly that has layers of information and I get it like so:
lsl <- unique(origAddress$LIHN_Line) # Gets unique service lines
# Create color palette
lihnpal <- colorFactor(
palette = 'Dark2'
, domain = origAddress$LIHN_Line
)
# create initial leaflet
LIHNMap <- leaflet() %>%
setView(lng = sv_lng, lat = sv_lat, zoom = sv_zoom) %>%
addTiles(group = "OSM (default)") %>%
addProviderTiles(providers$Stamen.Toner, group = "Toner") %>%
addProviderTiles(providers$Stamen.TonerLite, group = "Toner Lite") %>%
addControl("LIHN Service Line Point Map", position = "topright")
# for loop to cycle through adding layers
for(i in 1:length(lsl)){
LIHNMap <- LIHNMap %>%
addCircles(
data = subset(origAddress, origAddress$LIHN_Line == lsl[i])
, group = lsl[i]
, lat = ~lat
, lng = ~lon
, radius = 3
, fillOpacity = 1
, color = ~lihnpal(LIHN_Line)
, label = ~htmlEscape(LIHN_Line)
, popup = ~as.character(
paste(
"<strong>Hospitalist/Private: </strong>"
, hosim
, "<br><strong>Address: </strong>"
, FullAddress
, "<br><strong>Service Line: </strong>"
, LIHN_Line
, "<br><strong>LOS: </strong>"
, LOS
, "<br><strong>SOI: </strong>"
, SOI
, "<br><strong>Encounter: </strong>"
, pt_id
, "<br><strong>Payer Group:</strong>"
, pyr_group2
)
)
)
}
# add layercontrol
LIHNMap <- LIHNMap %>%
addLayersControl(
baseGroups = c("OSM (default)", "Toner", "Toner Lite"),
overlayGroups = lsl,
options = layersControlOptions(
collapsed = TRUE
, position = "topright"
)
)
LIHNMap <- LIHNMap %>%
addAwesomeMarkers(
lng = sv_lng
, lat = sv_lat
, icon = hospMarker
, label = ""
, popup = HospPopup
)
# print map
LIHNMap

Resources