Overview

In this example, we’ll create a Leaflet tilemap of New York City. We’ll use the nyc crime dataset to display counts of crimes committed over a 7-month period. And we will add a legend and color our circle markers different colors based on the type of crime that was committed.

Setup

Open up RStudio and a new R session. Let’s install Shiny if it is not already installed and load it.

# if Shiny is not installed, install it.
if (!require("shiny")) { install.packages("shiny", repos="http://cran.us.r-project.org") }
    
# Load the Shiny library
library(shiny)

Let’s create a folder in the current working directory entitled leaflet to hold our files and set it as our current working directory.

# Create a `leaflet` directory.
dir.create("leaflet")

# Set `leaflet` as our current working directory.
setwd("leaflet")

Now let’s create our starter files.

file.create("global.R")
file.create("server.R")
file.create("ui.R")

Loading Data

We will download the nyc crime dataset and save it in the leaflet directory.

Creating our Map

We will be using Leaflet to create our map, so we will need to include the leaflet library. First let’s install the leaflet package.

if (!require("leaflet")) { install.packages("leaflet", repos="http://cran.us.r-project.org")}
library(leaflet)

We will start with the global.R file. The global.R file stores all our global variables. Let’s edit it.

file.edit("global.R")

Copy the following into the global.R file:

# Loads the Shiny and leaflet libraries.
library(shiny)
library(leaflet)

# Saves the breakfast cereal dataset to the `cereals` variable.
crime <- read.csv("crime.csv", header=TRUE, stringsAsFactors=FALSE)

Save and close the global.R file. Let’s setup our server.R file. Open up the file.

file.edit("server.R")

We will need to build our map up step by step, so let’s start with the renderLeaflet function. And let’s save our map to an output variable.

shinyServer(function (input, output) {
  output$map <- renderLeaflet({})
})

Ok. Now lets define our map. First, we’ll instantiate the leaflet function, and we will pass it data for use later.

shinyServer(function (input, output) {
  output$map <- renderLeaflet({
    leaflet(crime)
  })
})

Next, we’ll set the default view.

shinyServer(function (input, output) {
  output$map <- renderLeaflet({
    leaflet(crime) %>%
    # set view to New York City
    setView(lng = -73.98928, lat = 40.75042, zoom = 10)
  })
})

Now, we’ll need to provide tiles. Let’s use the CartoDB.Positron tiles. There are of course others you could use. But we’ll stick with these for now.

shinyServer(function (input, output) {
  output$map <- renderLeaflet({
    leaflet(crime) %>%
    setView(lng = -73.98928, lat = 40.75042, zoom = 10) %>%
    addProviderTiles("CartoDB.Positron", options = providerTileOptions(noWrap = TRUE))
  })
})

So far, we have our map. And if we were to set up our ui.R file, we could display the map. So, let’s go ahead and do that now.

Open up the ui.R file and paste in the following:

shinyUI(
  # Use a fluid Bootstrap layout
  fluidPage(
    # Give the page a title
    titlePanel("NYC Crime Statistics"),
    mainPanel(leafletOutput("map"))
  )
)

If you have completed any of the Shiny tutorials, then you know exactly what’s happening in the code above. We are simply creating a fluid page layout with 2 rows, a titlePanel and a mainPanel for our map.

Now, let’s run our app.

runApp("../leaflet")

You should see a map of New York City.

## Warning: package 'shiny' was built under R version 3.1.3
## Warning: package 'leaflet' was built under R version 3.1.3

alt txt

Now that we have our map, let’s add our circles.

shinyServer(function (input, output) {
  output$map <- renderLeaflet({
    leaflet(crime) %>%
    setView(lng = -73.98928, lat = 40.75042, zoom = 10) %>%
    addProviderTiles("CartoDB.Positron", options = providerTileOptions(noWrap = TRUE)) %>%
    addCircleMarkers(
      lng=~longitude, # Longitude coordinates
      lat=~latitude, # Latitude coordinates
      radius=~TOT, # Total count
      stroke=FALSE, # Circle stroke
      fillOpacity=0.5, # Circle Fill Opacity
      # Popup content
      popup=~paste(
        "<b>", CR, "</b><br/>",
        "count: ", as.character(TOT), "<br/>",
        "date: ", as.character(MO), "/", as.character(YR)
      )
    )
  })
})

Let’s take a look.

alt text

Let’s add some color to our map by coloring the circles by the type of crime. First we will need to create a color function. We will use the colorFactor function to create our colors. The first argument is a color palette which we create using the topo.colors function. Here we want a palette of 7 colors. The next argument is the domain or the possible values that can be mapped. For more info on the colorFactor API, use the R help command.

shinyServer(function(input, output) {
  # Create our colors with a categorical color function
  color <- colorFactor(topo.colors(7), crime$CR)

  output$map <- renderLeaflet({
    map <- leaflet(crime) %>%
      setView(lng = -73.98928, lat = 40.75042, zoom = 10) %>%
      addProviderTiles("CartoDB.Positron", options = providerTileOptions(noWrap = TRUE)) %>%
      addCircleMarkers(
        lng=~longitude,
        lat=~latitude,
        radius=~TOT,
        stroke=FALSE,
        fillOpacity=0.5,
        color=~color(CR), # color circle by crime type
        popup=~paste(
          "<b>", CR, "</b><br/>",
          "count: ", as.character(TOT), "<br/>",
          "date: ", as.character(MO), "/", as.character(YR)
        )
      )
  })
})

You should now see different color circles on the map. You can click on a circle to get information regarding the type of crime, the count of times that crime was commited and the date.

alt text

Finally, let’s add a legend to our map so that its easy to identify the types of crimes being commited in NYC.

shinyServer(function(input, output) {
  # Create our colors with a categorical color function
  color <- colorFactor(topo.colors(7), crime$CR)

  output$map <- renderLeaflet({
    map <- leaflet(crime) %>%
      setView(lng = -73.98928, lat = 40.75042, zoom = 10) %>%
      addProviderTiles("CartoDB.Positron", options = providerTileOptions(noWrap = TRUE)) %>%
      addCircleMarkers(
        lng=~longitude,
        lat=~latitude,
        radius=~TOT,
        stroke=FALSE,
        fillOpacity=0.5,
        color=~color(CR),
        popup=~paste(
          "<b>", CR, "</b><br/>",
          "count: ", as.character(TOT), "<br/>",
          "date: ", as.character(MO), "/", as.character(YR)
        )
      ) %>%
      addLegend(
        "bottomleft", # Legend position
        pal=color, # color palette
        values=~CR, # legend values
        opacity = 1,
        title="Type of Crime Committed"
      )
  })
})

Lets take a look.

alt text Congrats! You’ve created you first Leaflet map with Shiny.

Exercises

  1. Try using different tiles in the leaflet map.

  2. Instead of Circle Markers, add Marker Clusters.

Advanced

  1. Add a timeseries chart with a brush, so that when you brush over a specific time window, you filter out the circle markers in the map that do not occur within that time span. Note: For an example of implementing a chart with a brush, check out the linked chart tutorial.