rstudio / leaflet Goto Github PK
View Code? Open in Web Editor NEWR Interface to Leaflet Maps
Home Page: http://rstudio.github.io/leaflet/
License: Other
R Interface to Leaflet Maps
Home Page: http://rstudio.github.io/leaflet/
License: Other
Hi Rstudio Team,
Thanks for your great work on this package.
I'd like to request a feature to allow default color handling for any column name that is passed via the scripting interface. Right now the color
argument works well when there is a string, a vector of colors, or a dataframe column of colors. However if you simply pass the name of any old column leaflet
cannot handle the data. To me, a best-guess representation of color in the spirit of ggplot
is desirable where leaflet can detect if the column is a string, a categorical variable, or a continuous variable.
library(leaflet)
#dataframe with lat/lon and a categorical and continuous variable
df = data.frame(Lat = 1:10,
Long = rnorm(10),
CatVar = sample(c("A","B","C"), 10, replace = T),
ConVar = rnorm(10))
#basemap
m = leaflet(df) %>% addTiles()
# these work
m %>% addCircles(color="red")
m %>% addCircles(color = topo.colors(10,alpha = NULL ))
#it would be great for these to have defaults as well
m %>% addCircles(color=~CatVar)
m %>% addCircles(color=~ConVar)
thanks,
zach cp
A click
event handler is added here each time the map receives an update, but it isn't cleared. This results in the data being sent to the server more and more times.
leaflet/inst/htmlwidgets/leaflet.js
Lines 529 to 535 in 8353463
The same may be true for the moveend
event a few lines below.
Edit: I think that shiny.onInputChange
may collapse multiple calls into a single data item sent to the server. But shiny.onInputChange
is still called an increasing number of times as more clicks occur.
If I install via install_github then the package works fine. But if I pull it and try load_all("./leaflet") then the resulting web page is blank.
The HTML is there, but bits are missing. The head is:
<head>
<meta charset="utf-8"/>
<script src="lib/htmlwidgets-0.3.2/htmlwidgets.js"></script>
<script src="lib/leaflet-binding-0.0.10/leaflet.js"></script>
</head>
whereas a working install has some other script tags and I guess that pulls in the code that does the work. Is the package trying to get some things that aren;t in the right place when its not truly installed?
Or am I doing it wrong again...
This a minor thing. The arguments for methods.fitBounds
in inst/htmlwidgets/leaflet.js do not match the order of arguments in leaflet::fitBounds
. The lat's and lng's are flipped:
methods.fitBounds = function(lat1, lng1, lat2, lng2)
fitBounds <- function(map, lng1, lat1, lng2, lat2)
Since both can be called from R, perhaps it would be good to have them match.
Thanks.
This is a cross post from SO
I would like to be able to replicate the Interactive Chroropleth Map example from leafletjs using R's leaflet
package, which has an intro here
However, I seem to be struggling even at the first few hurdles...
Below is what I have done so far:
library(dplyr)
library(leaflet)
# Download js file
download.file('http://leafletjs.com/examples/us-states.js',destfile='us-states.js')
# Generate base map (but not sure how to add the js file data)...
m = leaflet() %>% addTiles() %>% setView(-96,37.8,zoom=4)
m
If possible, I think that this would be quite a good example to come with the package....
This is similar to issue #22 but I'm trying to work with lines instead of markers.
I have a number of tracks in a data.frame
where the structure is (ttid, lng, lat). Using the points_to_lines
function from (https://rpubs.com/walkerke/points_to_line) I was able to convert it into a SpatialLines
object and plot it with leaflet. However when I try to embed it in an RMarkdown document, I get an error:
> Error in `[.data.frame`(x@data, i, j, ..., drop = FALSE) :
> undefined columns selected
This code run at the console in RStudio works (it produces two different lines)
tracks <- data.frame(ttid=c(rep("foo",3),rep("bar",3)), lng = c(1:3, 1:3), lat = c(rep(0, 3),rep(1,3)), stringsAsFactors = F)
lls <- points_to_line(tracks, "lng","lat", id_field = "ttid")
leaflet(lls) %>% addTiles() %>% addPolylines()
This example RMarkdown document does not work. I did verify that your previous example from #22 does work on my system.
---
output: html_document
runtime: shiny
---
```{r, echo=FALSE}
library(sp)
library(maptools)
points_to_line <- function(data, long, lat, id_field = NULL, sort_field = NULL) {
# Convert to SpatialPointsDataFrame
coordinates(data) <- c(long, lat)
# If there is a sort field...
if (!is.null(sort_field)) {
if (!is.null(id_field)) {
data <- data[order(data[[id_field]], data[[sort_field]]), ]
} else {
data <- data[order(data[[sort_field]]), ]
}
}
# If there is only one path...
if (is.null(id_field)) {
lines <- SpatialLines(list(Lines(list(Line(data)), "id")))
return(lines)
# Now, if we have multiple lines...
} else if (!is.null(id_field)) {
# Split into a list by ID field
paths <- split(data, data[[id_field]])
sp_lines <- SpatialLines(list(Lines(list(Line(paths[[1]])), "line1")))
# I like for loops, what can I say...
for (p in 2:length(paths)) {
id <- paste0("line", as.character(p))
l <- SpatialLines(list(Lines(list(Line(paths[[p]])), id)))
sp_lines <- spRbind(sp_lines, l)
}
return(sp_lines)
}
}
```
```{r}
library(leaflet)
library(shiny)
renderLeaflet({
tracks <- data.frame(ttid=c(rep("foo",3),rep("bar",3)), lng = c(1:3, 1:3), lat = c(rep(0, 3),rep(1,3)), stringsAsFactors = F)
lls <- points_to_line(tracks, "lng","lat", id_field = "ttid")
leaflet(lls) %>% addTiles() %>% addPolylines()
})
```
I'm working with the feature/color-legend branch.
I use colorBin with unemployment data. This is the code:
colorBin('YlOrRd', leedsShape@data$Unemployed_, bins= 5 ,na.color = "#808080")
...
attr(,"colorArgs")$bins
[1] 0 2 4 6 8 10 12 14
If I use bins=5
I get 8 bins. I get 8 bins with bins=6
all the way to bins=8
.
bins=9
gives 13! (the 'YlOrRd' palette gets up to 9 colours).
If I use bins=4
I get four bins:
colorBin('YlOrRd', leedsShape@data$Unemployed_, bins= 4 ,na.color = "#808080")
...
attr(,"colorArgs")$bins
[1] 0 5 10 15
As leedsShape@data$Unemployed_,
is the vector with the actual data (including NA) I've tried to give the domain as a range ( 0:12.83
or c(0, 12.83
).
Using domain= c(0,12.83)
:
If I use bins=4
I get four bins. I get 8 bins with bins=6
all the way to bins=8
.
Using domain= 0:12.83
:
If I use bins=4
I get four bins. I get 7 bins with bins=6
all the way to bins=8
.
There exist (at least) two other R-packages for leaflet:
https://github.com/jcheng5/leaflet-shiny
https://github.com/chgrl/leafletR
What is the difference to this package, and when and why should I use which one?
I am following up on a question asked in the shiny list (https://groups.google.com/forum/#!topic/shiny-discuss/E6YEJuIGkRs): The approach Yihui suggested did not work for me. My end goal is to pass a column name whose values are names of images (abc.jpg, xyz,jpg), from a dataframe to iconUrl to place markers with images of those names on a map. Those images are provided in the www folder of a shiny app. How will this work?
Sorry not sure if you view new comments to #32 as it is closed
Thanks very much for this (addLegend).
I want to use it in shiny with the user being able to change the number of bins via a numericInput.
However, the existing legend is not removed
library(leaflet)
m = leaflet() %>% tileLayer()
m # a map with the default OSM tile
# move the center to Snedecor Hall
m = m %>% setView(c(42.0285, -93.65), zoom = 17)
rand_lat = function(n = 10) rnorm(n, 42.0285, .01)
rand_lng = function(n = 10) rnorm(n, -93.65, .01)
# polyline
m %>% mapPolyline(rand_lat(50), rand_lng(50))
# polygon
m %>% mapPolygon(rand_lat(), rand_lng(), layerId = 'foo')
For example, this demo app re-zooms every time the data reloads. Because the data reloads automatically, this can be an interruption: https://winston.shinyapps.io/buses/
It would be nice to have an option to turn this off.
I'd also like to have a button that resets the zoom so it contains all the markers. Is it possible to send a command from the R side to tell it to do this?
Is possible (or will it be possible with the new design) to display at the same time on the same map:
In case, is there an example of it?
Pandoc was also complaining during compile time about a URL that ended with #default#VML
, I fixed that in d142e34. We will need to apply that patch every time we update Leaflet from upstream.
Hi, could you clarify which version of the leaflet package is to be developed and maintained in the future? I have been using jcheng5 for now, but see more updates in this repo now.
This is a very useful package, would like to see support for quick legends and for re-symbolizing existing layers in the client (instead of having to pass complete features with each request).
Thanks for the hard work, --Mel.
Hi is it possible or planned to support leaflet's ImageOverlay: http://leafletjs.com/reference.html#imageoverlay
Specifically I'd like to add a transparent plot generated by R to the map (some splines through the markers), which should be zoomed/panned etc when the map is.
This is really an htmlwidgets issue. I guess we do not really need to carry the raw data to the HTML page, e.g. for
leaflet(data = df) %>% addTiles() %>% addCircles(~lat, ~lng, color = ~color)
The result will be list(data = df, tileLayer = ..., circle = list(lat, lng, list(color = ...))
. The whole thing is converted to JSON and inserted in HTML, but this may be of concern when df is relatively large and we do not really need it to be converted to JSON. So we may need a way for htmlwidgets::createWidget() to discard certain elements from x
.
hello everyone,
My name is Myriam and I live in tunisia
ย currently doing my research paper for devolloper an application with language R and shiny framework for the first step I have some questions to help me move I have written class R & I'll tcl tk convert to shiny but I do not know how to do to convert so I really would like you to help me to solve this problem
and thank you in advance
There doesn't seem to be a way to set the map dimensions when it is created in a Shiny interactive document (.Rmd file with runtime: shiny). In this case the map is rendered using renderLeaflet() and the default parameters to leafletOutput() are used. Is there a way to do this? Thanks!
Is it possible to add more complex objects like ggplots?
For example I might have a data.frame with columns lat, long, x, y:
lat, long, x, y
40, 5, 1, 6
40, 5, 2, 8
40, 5, 5, 3
41, 7, 3, 9
41, 7, 7, 10
41, 7, 9, 13
and I would like to build two ggplots(...) + geom_line(...)
- one for 40, 5 and one for 41, 7 - which are printed as embetted graphs on their respective coordinates, namely 40, 5 and 41, 7.
Would that be possible and if so, how?
If not, what would be an option? (E.g. a different package instead of rstudio/leaflet or a different package instead of ggplot2.)
I have a choropleth style leaflet map which works fine in Rmarkdown as long as it does not have shiny runtime.
As soon as I add this (without any shiny elements - although I did try adding library(shiny) and library(knitr) to no avail) I get this error
Error in polygonData.default(data) :
Don't know how to get path data from object of class data.frame
Here is code
library(rgdal)
library(leaflet)
library(dplyr)
library(WDI)
## Download data from Natural Earth
url <- "http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/50m/cultural/ne_50m_admin_0_countries.zip"
tmp <- tempdir()
file <- basename(url)
download.file(url, file)
unzip(file, exdir = tmp)
## Read the data into R
countries <- readOGR(dsn=tmp,
layer = "ne_50m_admin_0_countries",
encoding = "UTF-8")
# ## Pull data from the World Bank API
dat <- WDI(country = "all",
indicator = "SP.DYN.LE00.IN", # life expectancy at birth
start = 2012,
end = 2012)
dat$SP.DYN.LE00.IN <- round(dat$SP.DYN.LE00.IN, 1)
#
# ## Perform the merge. The sort = FALSE argument is crucial here - but be sure to double-check as merge
# ## can behave badly with spatial objects in R.
#
#
countries2 <- merge(countries,
dat,
by.x = "iso_a2",
by.y = "iso2c",
sort = FALSE)
pal <- colorQuantile("RdBu", NULL, n = 6)
country_popup <- paste0("<strong>Country: </strong>",
countries2$country,
"<br><strong>Life expectancy at birth, 2012: </strong>",
countries2$SP.DYN.LE00.IN)
mb_tiles <- "http://a.tiles.mapbox.com/v3/kwalkertcu.l1fc0hab/{z}/{x}/{y}.png"
mb_attribution <- 'Mapbox <a href="http://mapbox.com/about/maps" target="_blank">Terms & Feedback</a>'
df <- data.frame(Age_Range=levels(cut(countries2$SP.DYN.LE00.IN,6)))
## Create the map
leaflet(data = countries2) %>%
addTiles(urlTemplate = mb_tiles,
attribution = mb_attribution) %>%
addPolygons(fillColor = ~pal(SP.DYN.LE00.IN),
fillOpacity = 0.8,
color = "#BDBDC3",
weight = 1,
popup = country_popup)
Without addPolygons runtime: shiny does work - but, of course, provides no info on the map
It looks like each time a renderLeaflet
re-executes, it will add points to the map, but it won't remove them.
In this example app, when you select different bus routes, it will add new points but not remove them. This makes it hard to use with data sources that change.
library(shiny)
library(leaflet)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
uiOutput("routeSelect")
),
mainPanel(
leafletOutput("busmap")
)
)
)
# Download data from the Twin Cities Metro Transit API
# http://svc.metrotransit.org/NexTrip/help
getMetroData <- function(path) {
url <- paste0("http://svc.metrotransit.org/NexTrip/", path, "?format=json")
jsonlite::fromJSON(url)
}
routes <- getMetroData("Routes")
server <- function(input, output) {
output$routeSelect <- renderUI({
routeNums <- sort(as.numeric(routes$Route))
selectInput("routeNum", "Route", choices = routeNums)
})
vehicleLocations <- reactive({
if (is.null(input$routeNum))
return(NULL)
getMetroData(paste0("VehicleLocations/", input$routeNum))
})
output$busmap <- renderLeaflet(quoted = TRUE, quote({
locations <- vehicleLocations()
if (is.null(locations))
return(NULL)
# Four possible directions for bus routes
dirPal <- colorFactor(
c("#595490", "#527525", "#A93F35", "#BA48AA"),
c("1", "2", "3", "4")
)
leaflet(locations) %>%
addTiles() %>%
addCircleMarkers(
~VehicleLongitude,
~VehicleLatitude,
color = ~dirPal(Direction)
)
}))
}
shinyApp(ui, server)
Hi,
Is there a way to use leaflet event via the package or do you think about integrate that in the futur ?
It can be very usefull !
It would be helpful to both be able to set an initial view (either with setView or fitBounds) and to have a user-selected view be retained when new data is rendered. Right now it seems like it's either one or the other. For example, if I don't define an initial view and use mapOptions(zoomToLimits = "first"), the view will initially cover the extent of the data and will retain the user-selected view, as desired. But if I have an explicit call to setView in there to default to a subset of the data's extent, the setView command is referenced on each rendering and there is no way to retain a user-selected view. Maybe this could be addressed by adding an option to setView so that it interacts with zoomToLimits.
Hello, is it possible to add legend to the map? I'd like to legend colors by groups.
Very thanks.
If I create a chroropleth map of the US states, using addPolygons, is it possible to have an event which would select the chosen state so that county map data / and a resultant map of that state alone can be produced?
Is it possible to use the Stamen map tiles in the leaflet
package similar to what Ramnath did in his Citibike visualization?
Thanks for what is going to be a great package.
I think this line should use leaflet=leaflet
:
Line 17 in 90a56e9
and I guess rectangles should also be polygons
When adding a leaflet map dynamically to a Shiny app, it shows up as expected. For example:
shinyApp(
ui = bootstrapPage(div(
leafletOutput("leaflet")
)),
server = function(input, output) {
output$leaflet <- renderLeaflet({
leaflet() %>% addTiles() %>% setView(-93.65, 42.0285, zoom = 17)
})
}
)
But if the map is added statically, it doesn't show up.
shinyApp(
ui = bootstrapPage(div(
leaflet() %>% addTiles() %>% setView(-93.65, 42.0285, zoom = 17)
)),
server = function(input, output) { }
)
It would be useful in some cases to embed a static map into a Shiny app.
I think this is a sizing issue, similar to rstudio/dygraphs#12.
Hi
I have no problems creating a static leafletmap in rMarkdown. However I'm not sure how to render one where there is an input variable. This approach creates the data OK but does not render map.
observe({
data <- calcs involving input$var
glimpse(data) # confirmscorrect values in console
leaflet(data) %>%
addTiles() %>%
addCircleMarkers(info based on data)
})
should I be using renderLeaflet somehow or adding a binding similar to that used for ggvis in rMarkdown
wondering if we can set maxBounds for the map so the user cannot zoomout to space...thank you.
I wrote two little scripts: One for rstudio/leaflet one for leafletR (https://github.com/chgrl/leafletR).
If I execute the leaflet-script first and the leafletR-script second, everything works.
But if I execute the leafletR-script first and then the leaflet-script second I get the error
Error in browseURL(x, ...) : 'url' must be a non-empty character string
after
library(leaflet)
m = leaflet::leaflet()
m
How come? browseURL() is from the package utils. I tried to look into the code but did not find the use of browseURL(). What can I do to not get this error?
Hi,
I get a "Don't know how to get path data from object of class data.frame"
when I replace the "addCircles" with an "addPolylines" in the following code, but shouldn't it guess the proper columns in the very same way?
## app.R ##
library(shiny)
library(shinydashboard)
library(leaflet)
data(quakes)
dat = quakes
runApp(list(
ui = dashboardPage(
dashboardHeader(title = "quakes"),
dashboardSidebar(
sliderInput("slider", "#observations frequency:", 1, 100, 1)
),
dashboardBody(
leafletOutput("map", height = 600)
)
),
server = function(input, output) {
output$map <- renderLeaflet({
map <- leaflet() %>% addTiles()
map %>% addCircles(data=dat[seq(from = 1, to = nrow(dat), by=input$slider), ], #input$slider
fillOpacity = 1.0)
})
}
))
There are lots of leaflet plugins that are quite useful. The one I need is proj4leaflet, which allows the use of other map projections. My specific interest is to load the GIBS data from NASA using the polar stereographic projection for the Arctic. Here is an example.
Hi Rstudio Team,
This is a great package. I am writing a small package that uses Leaflet and I would love to see it on CRAN. It seems like this is your intention so I am just posting this issue to demonstrate interest.
thanks,
zach cp
At the moment every time I make a leaflet map this way I get a new tab in my browser and probably a new set of temp files as well. While it might be nice to have all the old maps I made, most of them are wrong in some way and hence useless.
If I could tell leaflet() to use the same temp dir then I could simply hit reload on my browser and get my new map version.
Even better than that would be to integrate a LiveReload server. This can be set to watch folders for file changes. A JS script in the web page listens for messages from that server (on port 35729) and reloads the page automatically. This does require one script tag in the HTML and for the user to run a LiveReload server (for which various options exist) watching the folder.
I think LiveReload would enhance most R packages that produce HTML output graphics... Who likes hitting reload or closing loads of tabs?
Is there a way to add layers to groups and enable the layer group control? Possibly related: what is the layerId parameter for? I would like to do something like this example:
http://leafletjs.com/examples/layers-control.html
though in my case the layers are polygons rather than markers.
I added my map using the leafletOutput() and leaflet() functions.
In my server.R I add a geoJson layer using:
map = map %>% addGeoJSON(features)
The features show up fine, but I can not track a click on the feature. Some debugging learned that in the leaflet.js in the geoJSON method it tries to register a click on the self.id (mapid) but it is not present at that time so it registers an "undefined" mapid.
Are styles included in geojson data passed to addGeoJSON()
used in map rendering? It seems as though they are not, but perhaps I'm missing something? e.g.,
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-122.26, 37.77]
},
"properties": {
"name": "Alameda CA",
"country.etc": "CA",
"pop": "70069",
"capital": "0",
"marker-color": "#DEEBF7"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-73.8, 42.67]
},
"properties": {
"name": "Albany NY",
"country.etc": "NY",
"pop": "93576",
"capital": "2",
"marker-color": "#9ECAE1"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-123.09, 44.62]
},
"properties": {
"name": "Albany OR",
"country.etc": "OR",
"pop": "45535",
"capital": "0",
"marker-color": "#3182BD"
}
}
]
}
those marker colors render on a github gist map, and geojson.io, but not using this package.
I'd like to have the default behavior of addCircles to ignore NA values. For example:
library(leaflet) #a super awesome package
leaflet_sample <- data.frame(lati = c(61.191, NA, 61.171), long = c(-149.895, NA, -149.875))
leaflet() %>% addTiles() %>%
setView(-149.885, 61.181, zoom = 11) %>% addCircles(lng = leaflet_sample$long, lat = leaflet_sample$lati,
color = "#ff0000")
#OR
leaflet() %>% addTiles() %>%
setView(-149.885, 61.181, zoom = 11) %>% addCircles(lng = leaflet_sample$long[!is.na(leaflet_sample$long)],
lat = leaflet_sample$lati[!is.na(leaflet_sample$lati)],
color = "#ff0000")
Thanks for any opinions if this is a worth feature request or not.
Leaflet has many features that are not accessible from shiny.
scrollWheelZoom is probably one of the most important ones for those who use Mac.
Without setting this to false, it zooms whenever you try to move around with mousepad gestures. It is a pain.
Please, consider implement a way to set/reset/access "hidden" leaflet features like this.
Tks
I had a play with the new legend added by @yihui - great work!.
I am using it to display unemployment % over population. I use colorBin to bin the unemployment percentages.
On the other hand the legend displays my percentages as absolute values.
It would be nice to be able to have a way to format the legend entries, as an option.
Vladimir Agafonkin produced this interesting leaflet plugin visible in http://leaflet.github.io/Leaflet.heat/demo/
The actual plug in is available here: https://github.com/Leaflet/Leaflet.heat
Is there a chance to see it added to the RStudio library?
Using some reference on the web I recently hacked a demo of it using rCharts & shiny, but it stopped to work on a recent version of shiny (issue documented here rstudio/shiny#642)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.