The guys at RStudio are simply awesome! I will tell you ‘why’ in a minute.
I was recently browsing for a package to create maps without coding in JavaScript. I tried using googleVis, rMaps, LeafletR, and a lot of other packages that output map-images, until I came across this package called Leaflet. My favorite feature from the package- compatibility with RMarkdown- produces a great experience of seamless zoomable, interactive maps in an HTML which is quite portable.
I get scared just writing HTML, JavaScript for me right now is far-far away! And then there was this package which now does not need me to leave my comfort zone (R-Rstudio) but still produces pretty-lookin’ maps!
Here is the project on Github: https://github.com/rstudio/leaflet
I am thankful to their blog for a lot of code which appears on this page: http://rstudio.github.io/leaflet/#installation-and-use Following are my experiments with Leaflet package.
Before starting to map the hell out of it, let us create a dummy data set. I know,this dataset can be created in ‘\(Infinity + 1\)’ ways, but as a lazy bum I am creating 3 vectors and combining them to create a table.
The table is a random collection of cities in US with their latitude-longitude pairs chosen in a most loose manner. The lat-long pairs are not exact, but are towns within the metro areas.
##### Location Names
Location <- c("Atlanta ","Los Angeles","Chicago","New York","Dallas","Baltimore","Phoenix","Charlotte","Houston","San Antonio", "Seattle" )
#### Latitude and Longitude values for each of the above location
Lat <- c(33.74401,33.82377,41.78798,40.767309,32.88153,39.148492,33.45444,35.2406,29.935842,29.44838,47.714965 )
Lon <- c(-84.56032,-118.2668,-87.7738,-73.978308,-96.64601,-76.796211,-112.32401,-81.04028,-95.398436,-98.39908,-122.127166 )
#### Some hypothetical number of orders shipped out of each location
Orders <- c(1992,2500,3600,2252,3650,3450,4145,3945,5050,4300,1987)
#### Let us create some hypothetical class flags for the cities
Type <- c(rep("Yoda",5),rep("Vader",6))
### Create data set from the above vectors
df <- data.frame(Location, Lat,Lon,Orders,Type)
This is how our dummy data set looks like!
## Location Lat Lon Orders Type
## 1 Atlanta 33.74401 -84.56032 1992 Yoda
## 2 Los Angeles 33.82377 -118.26680 2500 Yoda
## 3 Chicago 41.78798 -87.77380 3600 Yoda
## 4 New York 40.76731 -73.97831 2252 Yoda
## 5 Dallas 32.88153 -96.64601 3650 Yoda
## 6 Baltimore 39.14849 -76.79621 3450 Vader
## 7 Phoenix 33.45444 -112.32401 4145 Vader
## 8 Charlotte 35.24060 -81.04028 3945 Vader
## 9 Houston 29.93584 -95.39844 5050 Vader
## 10 San Antonio 29.44838 -98.39908 4300 Vader
## 11 Seattle 47.71496 -122.12717 1987 Vader
Now let us start experimenting with the maps. ##1. This is just a OSM tile layer, so the default world map (if you zoom in couple of times)
library(leaflet)
mymap <- leaflet() %>% addTiles()
mymap # a map with the default OSM tile layer
If you want to control the map tile layer, here is an example:
mymap <- mymap %>%
addTiles(
'http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpeg',
attribution = 'Tiles Courtesy of <a href="http://www.mapquest.com/">MapQuest</a> — Map data © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
) %>% setView(-97, 40, zoom = 4)
mymap
mymap %>% addPopups(-85.472059, 35.929550, '<b>This is Sparta!</b>, no really! This is Sparta, TN! ')
# add some circles to a map, using the dummy data we have created 'df'
mymap %>% addCircles(data=df)
## Assuming 'Lon' and 'Lat' are longitude and latitude, respectively
# you can also explicitly use Lat and Long
mymap %>% addCircles(data=df,lat= ~Lat, lng = ~Lon, radius = 50, color = '#ff0000')
mymap %>% addMarkers(data=df,df[1,"Lon"],df[1,"Lat"], icon = JS("L.icon({
iconUrl: 'http://icons.iconarchive.com/icons/artua/star-wars/128/Master-Joda-icon.png',
iconSize: [75, 75]
})"))
mymap %>% addMarkers(data=df,df[1,"Lon"],df[1,"Lat"], icon = JS("L.icon({
iconUrl: 'http://icons.iconarchive.com/icons/artua/star-wars/128/Master-Joda-icon.png',
iconSize: [75, 75]
})")) %>%
addPopups(-86.753660,36.181098, 'Atlanta...@#brrr@+-*`~|%&#^$$')
Yoda - http://icons.iconarchive.com/icons/artua/star-wars/128/Master-Joda-icon.png
Vader- http://icons.iconarchive.com/icons/artua/star-wars/128/Darth-Vader-icon.png
mymap %>% addMarkers(data=df,df[1,"Lon"],df[1,"Lat"],icon = JS("L.icon({
iconUrl: 'http://icons.iconarchive.com/icons/artua/star-wars/128/Master-Joda-icon.png',
iconSize: [60, 60]
})")) %>%
addPopups(data=df,df[1,"Lon"],df[1,"Lat"], as.character(df[1,"Location"])) %>%
addMarkers(data=df,df[2,"Lon"],df[2,"Lat"],icon = JS("L.icon({
iconUrl: 'http://icons.iconarchive.com/icons/artua/star-wars/128/Master-Joda-icon.png',
iconSize: [60, 60]
})")) %>%
addPopups(data=df,df[2,"Lon"],df[2,"Lat"], as.character(df[2,"Location"])) %>%
addMarkers(data=df,df[7,"Lon"],df[7,"Lat"],icon = JS("L.icon({
iconUrl: 'http://icons.iconarchive.com/icons/artua/star-wars/128/Darth-Vader-icon.png',
iconSize: [60, 60]
})")) %>%
addPopups(data=df,df[7,"Lon"],df[7,"Lat"], as.character(df[7,"Location"])) %>%
addMarkers(data=df,df[10,"Lon"],df[10,"Lat"],icon = JS("L.icon({
iconUrl: 'http://icons.iconarchive.com/icons/artua/star-wars/128/Darth-Vader-icon.png',
iconSize: [60, 60]
})")) %>%
addPopups(data=df,df[10,"Lon"],df[10,"Lat"], as.character(df[10,"Location"]))
This can be done in a faster way, by vectorizing. It can also be automated in a user-function.
##### Mapping Yoda icons only
mymap %>% addMarkers(as.vector(df[1:5,"Lon"]),as.vector(df[1:5,"Lat"]), icon = JS("L.icon({
iconUrl: 'http://icons.iconarchive.com/icons/artua/star-wars/128/Master-Joda-icon.png',
iconSize: [50, 50]
})"))
## %>% addPopups(as.vector(df[1:5,"Lon"]),as.vector(df[1:5,"Lat"]), as.character(df[1:5,"Location"]) )
##### Mapping Yoda and Vader locations together
mymap %>% addMarkers(as.vector(df[df$Type=="Yoda","Lon"]),as.vector(df[df$Type=="Yoda","Lat"]), icon = JS("L.icon({
iconUrl: 'http://icons.iconarchive.com/icons/artua/star-wars/128/Master-Joda-icon.png',
iconSize: [50, 50]
})")) %>%
addPopups(as.vector(df[df$Type=="Yoda","Lon"]),as.vector(df[df$Type=="Yoda","Lat"]), as.character(df[df$Type=="Yoda","Location"]) ) %>%
addMarkers(as.vector(df[df$Type=="Vader","Lon"]),as.vector(df[df$Type=="Vader","Lat"]), icon = JS("L.icon({
iconUrl: 'http://icons.iconarchive.com/icons/artua/star-wars/128/Darth-Vader-icon.png',
iconSize: [50, 50]
})")) %>%
addPopups(as.vector(df[df$Type=="Vader","Lon"]),as.vector(df[df$Type=="Vader","Lat"]), as.character(df[df$Type=="Vader","Location"]) )
Let us look at some other features next time!!
Happy experimenting with R and JS!