I want to display a CSV file via its coordinates using leaflet in R. I think leaflet is not being able to pick up the coordinates correctly, how can I fix this?
Sample Data
Point Name X Y
1 A 1393959 406726.6
2 B 1392820 407719.7
3 C 1394466 405740.5
4 D 1393543 407094.7
5 E 1395119 405969.7
6 F 1393557 406747.5
Code
library(tidyverse)
library(leaflet)
map_data = df
map_data$popup = paste("<b>Location #: </b>", map_data$Point,
"<br>", "<b>Longitude: </b>", map_data$X,
"<br>", "<b>Latitude: </b>", map_data$Y,
"<br>", "<b>Desciption </b>", map_data$Name)
leaflet(map_data, width = "100%") %>% addTiles() %>%
addTiles(group = "OSM (default)") %>%
addProviderTiles(provider = "Esri.WorldStreetMap",group = "World StreetMap") %>%
addProviderTiles(provider = "Esri.WorldImagery",group = "World Imagery") %>%
addMarkers(lng = ~X, lat = ~Y, popup = map_data$popup, clusterOptions = markerClusterOptions())
Current Plot
First convert the df into an sf object. Define the CRS which in my case is 2271. Reproject to 4326 to make it work with leaflet and run the rest of the code.
library(tidyverse)
library(sf)
library(sfheaders)
library(leaflet)
# Convert df to sf
df_sf = st_as_sf(x = df,
coords = c("X", "Y"),
crs = 2271)
# Reproject to WGS84
df_sf = st_transform(df_sf , 4326)
df_sf = sf_to_df(rocks_wgs_sf, fill = T)
# Create the map
map_data = df
map_data$popup = paste("<b>Location #: </b>", map_data$Point,
"<br>", "<b>Longitude: </b>", map_data$X,
"<br>", "<b>Latitude: </b>", map_data$Y,
"<br>", "<b>Desciption </b>", map_data$Name)
leaflet(map_data, width = "100%") %>% addTiles() %>%
addTiles(group = "OSM (default)") %>%
addProviderTiles(provider = "Esri.WorldStreetMap",group = "World StreetMap") %>%
addProviderTiles(provider = "Esri.WorldImagery",group = "World Imagery") %>%
addMarkers(lng = ~X, lat = ~Y, popup = map_data$popup, clusterOptions = markerClusterOptions())
Related
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()
I have 30 years data for 15 stations with average temperature and want to create an animation using r studio (leaflet). I was looking at the some codes but it not working. An explanation on how to create timeseries animation using leaflet in r studio would be helpfull.
# install libraray
library(sp)
library(raster)
library(leaflet)
Temp53Yrs_df <- read.csv("C:/Users/Sownal/Documents/53YearsTemp.csv")
View(Temp53Yrs_df)
#make plots for the points in the map
leaflet() %>%
addTiles() %>%
addCircleMarkers(lat = Temp53Yrs_df$lat,
lng = Temp53Yrs_df$long)
# Add Data for Average Yearly Annual Temperature
col_pal <- colorNumeric(palette = "viridis",
domain = Temp53Yrs_df$X1965, reverse = TRUE)
#make years plot in the map
leaflet() %>%
addTiles() %>%
addCircles(lat = Temp53Yrs_df$lat,
lng = Temp53Yrs_df$long,
color = col_pal(Temp53Yrs_df$X1965),
radius = 20000,
fillOpacity = 0.4,
label = Temp53Yrs_df$X1965) %>%
addLegend(Temp53Yrs_df, position = "bottomleft", pal = col_pal,
values = Temp53Yrs_df$X1965, title = "Average Temperature in Year
1965")
#make years plot in the map
leaflet() %>%
addTiles() %>%
addCircles(lat = Temp53Yrs_df$lat,
lng = Temp53Yrs_df$long,
color = col_pal(Temp53Yrs_df$X1966),
radius = 20000,
fillOpacity = 0.4,
label = Temp53Yrs_df$X1966) %>%
addLegend(Temp53Yrs_df, position = "bottomleft", pal = col_pal,
values = Temp53Yrs_df$X1966, title = "Average Temperature in Year
1966")
#make years plot in the map
leaflet() %>%
addTiles() %>%
addCircles(lat = Temp53Yrs_df$lat,
lng = Temp53Yrs_df$long,
color = col_pal(Temp53Yrs_df$X1967),
radius = 20000,
fillOpacity = 0.4,
label = Temp53Yrs_df$X1967) %>%
addLegend(Temp53Yrs_df, position = "bottomleft", pal = col_pal,
values = Temp53Yrs_df$X1967, title = "Average Temperature in Year
1967")
#make years plot in the map
leaflet() %>%
addTiles() %>%
addCircles(lat = Temp53Yrs_df$lat,
lng = Temp53Yrs_df$long,
color = col_pal(Temp53Yrs_df$X1968),
radius = 20000,
fillOpacity = 0.4,
label = Temp53Yrs_df$X1968) %>%
addLegend(Temp53Yrs_df, position = "bottomleft", pal = col_pal,
values = Temp53Yrs_df$X1968, title = "Average Temperature in Year
1968")
Sample Data is attached below
enter image description hereenter image description here
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 have the following code:
# Get unique list of groups needed
lsl <- unique(origAddress$LIHN_Line)
# create initial leaflet
mt <- 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")
# for loop to cycle through adding layers
for(i in 1:length(lsl)){
#l <- lsl[i]
mt <- mt %>%
addCircles(
data = subset(origAddress, origAddress$LIHN_Line == lsl[i])
, group = lsl[i]
, radius = 3
, fillOpacity = 0.6
)
}
# add layercontrol
mt <- mt %>%
addLayersControl(
baseGroups = c("OSM (default)", "Toner", "Toner Lite"),
overlayGroups = lsl,
options = layersControlOptions(collapsed = TRUE
, position = "bottomright")
) %>%
showGroup("Medical")
# print map
mt
The issue is that the showGroup() function is not working as I expected. I checked the element of the map and got the following:
<span> Medical</span>
So I am not understanding why only that group isn't showing.
I'm new to shiny. I want to make a shiny app that shows the spatial distribution of different parameters. I used meuse dataset from sp package.
Here is the code I used
library(sp)
library(rgdal)
library(ggmap)
library(leaflet)
library(dplyr)
library(shiny)
ui <- fluidPage(
mainPanel(
titlePanel("Copper (ppm)"),
leafletOutput("copper"),
titlePanel("Lead (ppm)"),
leafletOutput("lead"),
titlePanel("Zinc (ppm)"),
leafletOutput("zinc")
)
)
server <- function(input,output){
output$copper <- renderLeaflet({
data(meuse)
coordinates(meuse) <- 1:2
proj4string(meuse) <- CRS("+init=epsg:28992")
meuse <- spTransform(meuse, CRS("+proj=longlat +datum=WGS84"))
meuse_df <- as.data.frame(meuse)
leaflet(meuse_df) %>%
addProviderTiles("OpenStreetMap", group = "OpenStreetMap") %>%
addProviderTiles("Esri.WorldImagery", group = "Esri.WorldImagery") %>%
addCircleMarkers(~x,
~y,
radius = ~copper/10,
stroke = FALSE,
fillOpacity = 0.4,
group = "meuse_df",
popup = ~as.character(copper)) %>%
addLayersControl(position = "bottomleft",
baseGroups = c("OpenStreetMap",
"Esri.WorldImagery"),
overlayGroups = "meuse_df")
})
output$lead <- renderLeaflet({
leaflet(meuse_df) %>%
addProviderTiles("OpenStreetMap", group = "OpenStreetMap") %>%
addProviderTiles("Esri.WorldImagery", group = "Esri.WorldImagery") %>%
addCircleMarkers(~x,
~y,
radius = ~lead/50,
stroke = FALSE,
fillOpacity = 0.4,
group = "meuse_df",
popup = ~as.character(lead)) %>%
addLayersControl(position = "bottomleft",
baseGroups = c("OpenStreetMap",
"Esri.WorldImagery"),
overlayGroups = "meuse_df")
})
output$zinc <- renderLeaflet({
leaflet(meuse_df) %>%
addProviderTiles("OpenStreetMap", group = "OpenStreetMap") %>%
addProviderTiles("Esri.WorldImagery", group = "Esri.WorldImagery") %>%
addCircleMarkers(~x,
~y,
radius = ~zinc/100,
stroke = FALSE,
fillOpacity = 0.4,
group = "meuse_df",
popup = ~as.character(zinc)) %>%
addLayersControl(position = "bottomleft",
baseGroups = c("OpenStreetMap",
"Esri.WorldImagery"),
overlayGroups = "meuse_df")
})
}
shinyApp(ui = ui, server = server)
and here is the result I got
I wonder if there is a way to plot all parameters (copper, lead and zinc) on one map. Any suggestions would be appreciated.
UPDATE
Thanks to #Symbolix's answer and suggestion of using checkBoxGroupInput. Instead, I used addCircleMarkers three times so I can plot all the metals on one map and I can switch them on and off
ui <- fluidPage(
mainPanel(
titlePanel("All metals (ppm)"),
leafletOutput("metals")
)
)
server <- function(input,output){
output$metals <- renderLeaflet({
data(meuse)
coordinates(meuse) <- 1:2
proj4string(meuse) <- CRS("+init=epsg:28992")
meuse <- spTransform(meuse, CRS("+proj=longlat +datum=WGS84"))
meuse_df <- as.data.frame(meuse)
leaflet(meuse_df) %>%
addProviderTiles("OpenStreetMap", group = "OpenStreetMap") %>%
addProviderTiles("Esri.WorldImagery", group = "Esri.WorldImagery") %>%
addCircleMarkers(~x,
~y,
radius = ~copper/10,
color ="red",
stroke = FALSE,
fillOpacity = 0.4,
group = "copper",
popup = ~as.character(copper)) %>%
addCircleMarkers(~x,
~y,
radius = ~lead/50,
color ="gren",
stroke = FALSE,
fillOpacity = 0.4,
group = "lead",
popup = ~as.character(lead)) %>%
addCircleMarkers(~x,
~y,
radius = ~zinc/100,
color ="blue",
stroke = FALSE,
fillOpacity = 0.4,
group = "zinc",
popup = ~as.character(zinc)) %>%
addLayersControl(position = "bottomleft",
baseGroups = c("OpenStreetMap",
"Esri.WorldImagery"),
overlayGroups = c("copper",
"lead",
"zinc"))
})
}
shinyApp(ui = ui, server = server)
Melt your data so that your metals are in one column and you're good to go.
Here I use library(reshape2) to do the melt.
library(sp)
library(rgdal)
library(ggmap)
library(leaflet)
library(dplyr)
library(shiny)
library(reshape2)
ui <- fluidPage(
mainPanel(
titlePanel("Metals"),
leafletOutput("all_metals")
)
)
server <- function(input,output){
output$all_metals <- renderLeaflet({
data(meuse)
coordinates(meuse) <- 1:2
proj4string(meuse) <- CRS("+init=epsg:28992")
meuse <- spTransform(meuse, CRS("+proj=longlat +datum=WGS84"))
meuse_df <- as.data.frame(meuse)
## melt df so 'metals' are in one column
## using 'reshape2' library
meuse_melt <- melt(meuse_df, measure.vars = c("copper","lead","zinc"), variable.name = "metal")
## specify factor levels for colours
meuse_melt$metal <- factor(sample.int(5L, nrow(meuse_melt), TRUE))
factpal <- colorFactor(topo.colors(5), meuse_melt$metal)
## now you just need one output
leaflet(meuse_melt) %>%
addProviderTiles("OpenStreetMap", group = "OpenStreetMap") %>%
addProviderTiles("Esri.WorldImagery", group = "Esri.WorldImagery") %>%
addCircleMarkers(~x,
~y,
radius = ~value/100,
stroke = FALSE,
fillOpacity = 0.4,
group = "meuse_melt",
popup = ~metal,
color= ~factpal(metal)) %>%
addLayersControl(position = "bottomleft",
baseGroups = c("OpenStreetMap", "Esri.WorldImagery"), overlayGroups = "meuse_melt")
})
}
shinyApp(ui = ui, server = server)
To save you lines of code you could use mapview which provides multi-layer maps out of the box. If you only want certain attributes you can simply supply their names (or column numbers) to the 'zcol' argument. Alternatively, you can use 'burst = TRUE' to display all layers/columns present in the attribute table.
library(mapview)
library(sp)
data(meuse)
coordinates(meuse) <- ~x+y
proj4string(meuse) <- CRS("+init=epsg:28992")
mapview(meuse, zcol = c("copper", "lead", "zinc"))
## all layers
mapview(meuse, burst = TRUE)
mapview can be used with renderLeaflet.