Skip to content

For working with GeoJSON/TopoJSON data you have two options: either read it into sf data.frames; or use the addGeoJSON() and addTopoJSON() functions.

Reading as {sf}

The first approach is to use the sf packages to read GeoJSON/TopoJSON as sf data.frames. Then, you can use the full functionality of polygons, markers, colors, legends, etc.

# From https://eric.clst.org/tech/usgeojson/ and
# https://en.wikipedia.org/wiki/List_of_United_States_counties_and_county_equivalents
nycounties <- sf::read_sf("https://rstudio.github.io/leaflet/json/nycounties.geojson") 

pal <- colorNumeric("viridis", NULL)

leaflet(nycounties) %>%
  addTiles() %>%
  addPolygons(stroke = FALSE, smoothFactor = 0.3, fillOpacity = 1,
    fillColor = ~pal(log10(pop)),
    label = ~paste0(county, ": ", formatC(pop, big.mark = ","))) %>%
  addLegend(pal = pal, values = ~log10(pop), opacity = 1.0,
    labFormat = labelFormat(transform = function(x) round(10^x)))

This approach is preferred over using addGeoJSON()/addTopoJSON(), as it makes it easy to use feature properties in determining map colors, labels, etc., or to modify or add new properties.

The main downside to this approach is that it only supports feature collections where all features are of the same type, whereas in GeoJSON/TopoJSON it’s possible—though uncommon—to have a single feature collection that contains, say, both markers and polygons.

Working with raw GeoJSON/TopoJSON

addGeoJSON() and addTopoJSON() accept GeoJSON data in either parsed (nested lists) or stringified (single-element character vector) format.

Note that for larger JSON data, using parsed is significantly slower than using stringified, because parsed data must go through a JSON encoding step.

A simple example using stringified data:

topoData <- readLines("https://rstudio.github.io/leaflet/json/us-10m.json") %>% paste(collapse = "\n") 

leaflet() %>% setView(lng = -98.583, lat = 39.833, zoom = 3) %>%
  addTiles() %>%
  addTopoJSON(topoData, weight = 1, color = "#444444", fill = FALSE)

Styling raw GeoJSON/TopoJSON

You can modify the style of GeoJSON/TopoJSON features in a few ways. (Currently only paths and shapes can be styled; marker styling is not supported.)

One way to apply styles to all of the features is to use the arguments directly with addGeoJSON()/addTopoJSON(). Another way is to encode styling information directly in the JSON object/string by putting a style object directly underneath the top level JSON object.

You can provide feature-specific styles by annotating each feature’s property object with a style: {...} object. The feature-specific styles have the highest precedence, then the top-level style object, and finally the style-related arguments passed to the function.

See Leaflet’s path options for available style properties.

The previous example demonstrated the style arguments. Below is a more involved example that sets both global styles and per-feature styles directly into the JSON object.

(This approach is not recommended for applying styling in R; instead, use the approach described above where we convert to sf first. However, if you have control over the process that generates the GeoJSON in the first place, you might use these techniques to put the styling information directly in the JSON.)

library(jsonlite)

# From http://data.okfn.org/data/datasets/geo-boundaries-world-110m
geojson <- readLines("https://rstudio.github.io/leaflet/json/countries.geojson", warn = FALSE) %>%
  paste(collapse = "\n") %>%
  fromJSON(simplifyVector = FALSE)

# Default styles for all features
geojson$style = list(
  weight = 1,
  color = "#555555",
  opacity = 1,
  fillOpacity = 0.8
)

# Gather GDP estimate from all countries
gdp_md_est <- sapply(geojson$features, function(feat) {
  feat$properties$gdp_md_est
})
# Gather population estimate from all countries
pop_est <- sapply(geojson$features, function(feat) {
  max(1, feat$properties$pop_est)
})

# Color by per-capita GDP using quantiles
pal <- colorQuantile("Greens", gdp_md_est / pop_est)
# Add a properties$style list to each feature
geojson$features <- lapply(geojson$features, function(feat) {
  feat$properties$style <- list(
    fillColor = pal(
      feat$properties$gdp_md_est / max(1, feat$properties$pop_est)
    )
  )
  feat
})

# Add the now-styled GeoJSON object to the map
leaflet() %>% addGeoJSON(geojson)