I have a code below, and I would like to forloop the overlayGroup by each cluster. Many thanks in advance.
library(dplyr); library(leaflet); library(raster);library(htmltools)
cluster <- c("1st.C", "2nd.C", "3rd.C")
lat <- c(40.8518, 42.6611, 37.3089)
long <- c(14.2681, 13.6987, 13.5858)
data <- data.frame(cluster, lat, long); data
adm <- raster::getData('GADM', country= "italy" , level=1)
map_layers <- function() {
#number of groups
k <- n_distinct(data$cluster)
#base map
map <- leaflet() %>%
addProviderTiles(providers$CartoDB.Positron)
#loop through all groups and add a layer one at a time
for (i in 1:k) {
map <- map %>%
addCircleMarkers(
data = data %>% filter(cluster == i), group = as.character(i),
radius = 3, lng = ~long, lat = ~lat
)
}
#create layer control
map %>%
addLayersControl(
overlayGroups = c(1:k),
options = layersControlOptions(collapsed = FALSE)) %>%
hideGroup(as.character(c(2:k))) #hide all groups except the 1st one
}
#plot the map
map_layers()
i think this is what you are trying to achieve:
leaflet() %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addCircleMarkers(data = data,
radius = 3, lng = ~long, lat = ~lat, group = cluster) %>%
addLayersControl(overlayGroups = cluster,
options = layersControlOptions(collapsed = FALSE)) %>%
hideGroup(group = data$cluster[2:3])
Related
Here is my code:
m <- leaflet() %>%
addProviderTiles(providers$Stamen.Toner) %>%
setView(lng = -107.9917071, lat = 59.5, zoom = 3.5) %>%
addPolygons(data = plant,
color = "#660000",
weight = 1,
smoothFactor = 0.5) %>%
addCircleMarkers(lng = plant$lon, lat = plant$lat)
m
No matter what I try I get the following error message:
Error in polygonData.default(data) : Don't know how to get path
data from object of class spec_tbl_df
My data frame from which my data comes is a simple 5 row by 3 columns of coordinates and the name of the place.
Thoughts?
You had point data, not polygons.
library(leaflet)
plant <- data.frame(
stringsAsFactors = FALSE,
Name = c("University","University",
"University","University","University"),
lat = c(43.5339923, 49.8091536, 3.52682, 49.2519564, 45.5069177),
lon = c(-80.2244647,-97.1330418,
-113.5244937,-123.2465285,-73.5791163)
)
leaflet() %>%
addProviderTiles(providers$Stamen.Toner) %>%
setView(lng = -107.9917071, lat = 59.5, zoom = 3.5) %>%
# I removed the addPolygons(), you are adding points, not polygons
addCircleMarkers(lng = plant$lon, lat = plant$lat)
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.
I would like to add OpenStreetMap, OpenTopoMap and Stamen.TonerLines in a list to a leaflet map.
I get those names with
library("leaflet"); library("leafem")
names(providers)[c(1,10,40)]
[1] "OpenStreetMap" "OpenTopoMap" "Stamen.TonerLines"
My map is this
n = leaflet() %>%
addTiles(group = "Base") %>%
setView( lng = 1, lat = 40, zoom = 5 )
n
My lapply code is this
lapply(
c(1,10,40),
function(i) addProviderTiles(map=n, names(providers)[i], layerId = i, group =names(providers)[i])
)
lapply(
c(1,10,40),
function(i) addLayersControl(map=n, baseGroups = names(providers)[i])
)
Now I have only last tile!
How could I add those tiles using lapply?
You could do something like this
n = leaflet() %>%
addTiles(group = "Base") %>%
setView( lng = 1, lat = 40, zoom = 5 )
n %>% addProviderTiles(providers$OpenStreetMap, group = 'OpenStreetMap') %>%
addProviderTiles(providers$OpenTopoMap, group='OpenTopoMap') %>%
addLayersControl(baseGroups = c('OpenStreetMap', 'OpenTopoMap'))
To wrap into a function calling index
layered_map <- function(..., provider=NULL, base_map_name="Base") {
select_providers <- provider[c(...)]
iter <- function(providers, layerid) {
if (length(providers)==0) {
leaflet() %>% addTiles(group = base_map_name) %>% setView(lng = 1, lat = 40, zoom = 5 )
} else {
iter(providers[-length(providers)], layerid-1) %>%
addProviderTiles(providers[[length(providers)]],
layerId = layerid,
group = providers[[length(providers)]])
}
}
controlnames <- if (length(select_providers)==0) base_map_name else names(select_providers)
iter(select_providers, length(select_providers)) %>% addLayersControl(baseGroups = controlnames)
}
To call the function:
library("leaflet")
library("leafem")
layered_map(1, 10, 40, provider=providers)
It is quite generic. So, if you want to generate a base map without additional layers. You could simply do
layered_map()
or
layered_map(base_map_name="My base map")
which will give you
I can't seem to find any way to make the leaflet path a gradient based on another variable. For a given dataframe using lat/lng pairs from below:
df <- data.frame(lat = lat, lng = lng, var = c(1:25))
So the leaflet plot should look like:
leaflet() %>%
addTiles() %>%
addPolylines(data = df, lng = ~lng, lat = ~lat,
color = ~var)
But this will just color the whole path the same color.
Even if I do:
pal <- colorNumeric(
palette = "Blues",
domain = df$var)
leaflet() %>%
addTiles() %>%
addPolylines(data = df, lng = ~lng, lat = ~lat,
color = ~pal(var))
This doesn't work either.
Reproducible Example:
df <- data.frame(lat = rnorm(40) * 2 + 13,
lng = rnorm(40) + 48,
var = c(1:40))
pal <- colorNumeric(
palette = "Blues",
domain = df$var)
leaflet() %>%
addTiles() %>%
addPolylines(data = df, lng = ~lng, lat = ~lat,
color = ~pal(var))
Somewhat late to the party, but as SymbolixAU wrote, you'll need a separate Polyline for each row in the dataset. Full example below:
library(leaflet)
library(dplyr)
library(grDevices)
set.seed(1234)
df <- data.frame(lat = rnorm(40) * 2 + 13,
lng = rnorm(40) + 48,
var = c(1:40))
gradientFunction <- colorRampPalette(c("white", "blue"))
colorGradient <- gradientFunction(dim(df)[1])
df1 <- df %>%
mutate(nextLat = lead(lat),
nextLng = lead(lng),
color = colorGradient
)
gradient_map <- leaflet() %>%
addTiles()
for (i in 1:nrow(df1)) {
gradient_map <- addPolylines(map = gradient_map,
data = df1,
lng = as.numeric(df1[i, c('lng', 'nextLng')]),
lat = as.numeric(df1[i, c('lat', 'nextLat')]),
color = as.character(df1[i, c('color')])
)
}
gradient_map
I want to use different icons in a leaflet plot in R based on a factor variable in a dataframe. The factor variable might have 100 different levels, but I only have icons for a few levels, maybe 10 or so. If there is an icon I want to use it, else draw CircleMarkers.
I can do this with a for loop:
library(leaflet)
# Some icons
fruits_icons <- iconList(
apple = makeIcon("apple.png", iconWidth = 20, iconHeight = 20),
banana = makeIcon("banana.png", iconWidth = 20, iconHeight = 20)
)
# Some data
latitude <- 48 + runif(20)
longitude <- 10 + runif(20)
fruit <- sample(c("banana", "apple", "pear"), 20, replace = TRUE)
df <- data.frame(latitude, longitude, fruit)
map <- leaflet(df) %>% addTiles()
# check if fruit is in names(icons), then use icons, else circles
for(i in seq_len(nrow(df))){
if(df$fruit[i] %in% names(fruits_icons)){
map <- map %>% addMarkers(lng = df$longitude[i],
lat = df$latitude[i],
icon = ~fruits_icons[df$fruit[i]])
} else {
map <- map %>% addCircleMarkers(lng = df$longitude[i],
lat = df$latitude[i])
}
}
map
Is there a better way to do this without the for loop?
You can just subset the data that you want to use in each of the add*() methods
leaflet() %>% addTiles() %>%
addMarkers(data = df[df$fruit %in% names(fruits_icons),],
lng = ~longitude,
lat = ~latitude,
icon = ~fruits_icons[fruit]) %>%
addCircleMarkers(data = df[!df$fruit %in% names(fruits_icons), ],
lng = ~longitude,
lat = ~latitude)