lawn is an R wrapper for the Javascript library turf.js for advanced geospatial analysis. In addition, we have a few functions to interface with the geojson-random Javascript library.

lawn includes traditional spatial operations, helper functions for creating GeoJSON data, and data classification and statistics tools.

There is an additional helper function (see view()) in this package to help visualize data with interactive maps via the leaflet package (https://github.com/rstudio/leaflet). Note that leaflet is not required to install lawn - it’s in Suggests, not Imports or Depends.

Install

If installing leaflet

devtools::install_github("rstudio/leaflet")

Stable lawn version from CRAN

install.packages("lawn")

Or, the development version from Github

devtools::install_github("ropensci/lawn")
library("lawn")

Make some geojson data

Point

lawn_point(c(-74.5, 40))
#> <Point>
#>   Bounding box: -74.5 40.0 -74.5 40.0
#>   Coordinates: -74.5 40.0
#>   Properties: NULL

Polygon

rings <- list(list(
  c(-2.275543, 53.464547),
  c(-2.275543, 53.489271),
  c(-2.215118, 53.489271),
  c(-2.215118, 53.464547),
  c(-2.275543, 53.464547)
))
lawn_polygon(rings)
#> <Polygon>
#>   Bounding box: -2.3 53.5 -2.2 53.5
#>   No. points: 5
#>   Properties: NULL

count

Count number of points within polygons

lawn_count(polygons = lawn_data$polygons_count, points = lawn_data$points_count, "population")
#> <FeatureCollection>
#>   Bounding box: -112.1 46.6 -112.0 46.6
#>   No. features: 2
#>   No. points: 20
#>   Properties: 
#>     values count
#> 1 200, 600     2
#> 2              0

average

Average value of a field for a set of points within a set of polygons

lawn_average(polygons = lawn_data$polygons_average,
             points = lawn_data$points_average, 
             in_field = 'population')
#> <FeatureCollection>
#>   Bounding box: 10.7 59.9 10.9 59.9
#>   No. features: 2
#>   No. points: 20
#>   Properties: 
#>          values average
#> 1 200, 600, 100     300
#> 2      200, 300     250

distance

Define two points

from <- '{
 "type": "Feature",
 "properties": {},
 "geometry": {
   "type": "Point",
   "coordinates": [-75.343, 39.984]
 }
}'
to <- '{
  "type": "Feature",
  "properties": {},
  "geometry": {
    "type": "Point",
    "coordinates": [-75.534, 39.123]
  }
}'

Calculate distance, default units is kilometers (default output: km)

lawn_distance(from, to)
#> [1] 97.15958

random set of points

lawn_random(n = 2)
#> <FeatureCollection>
#>   Bounding box: -26.8 -84.1 86.5 21.6
#>   No. features: 2
#>   No. points: 4
#>   Properties: NULL
lawn_random(n = 5)
#> <FeatureCollection>
#>   Bounding box: -165.5 -62.1 53.1 87.6
#>   No. features: 5
#>   No. points: 10
#>   Properties: NULL

random features with geojson-random

Positions

gr_position()
#> [1]  17.02743 -38.50832

Points

gr_point(2)
#> <FeatureCollection>
#>   Bounding box: -35.7 -43.7 84.4 -6.7
#>   No. features: 2
#>   No. points: 4
#>   Properties: NULL

Polygons

gr_polygon(n = 1, vertices = 5, max_radial_length = 5)
#> <FeatureCollection>
#>   Bounding box: 86.4 -50.0 92.0 -43.2
#>   No. features: 1
#>   No. points: 12
#>   Properties: NULL

sample from a FeatureCollection

dat <- lawn_data$points_average
lawn_sample(dat, 1)
#> <FeatureCollection>
#>   Bounding box: 10.7 59.9 10.7 59.9
#>   No. features: 1
#>   No. points: 2
#>   Properties: 
#>   population
#> 1        600
lawn_sample(dat, 2)
#> <FeatureCollection>
#>   Bounding box: 10.8 59.9 10.8 59.9
#>   No. features: 2
#>   No. points: 4
#>   Properties: 
#>   population
#> 1        200
#> 2        300
lawn_sample(dat, 3)
#> <FeatureCollection>
#>   Bounding box: 10.7 59.9 10.8 59.9
#>   No. features: 3
#>   No. points: 6
#>   Properties: 
#>   population
#> 1        600
#> 2        300
#> 3        200

extent

lawn_extent(lawn_data$points_average)
#> [1] 10.71579 59.90478 10.80643 59.93162

within

lawn_within(lawn_data$points_within, lawn_data$polygons_within)
#> <FeatureCollection>
#>   Bounding box: -46.6 -23.6 -46.6 -23.6
#>   No. features: 2
#>   No. points: 4
#>   Properties: NULL

buffer

dat <- '{
 "type": "Feature",
 "properties": {},
 "geometry": {
     "type": "Polygon",
     "coordinates": [[
       [-112.072391,46.586591],
       [-112.072391,46.61761],
       [-112.028102,46.61761],
       [-112.028102,46.586591],
       [-112.072391,46.586591]
     ]]
   }
}'
lawn_buffer(dat, 1, "miles")
#> <Feature>
#>   Type: Polygon
#>   Bounding box: -112.1 46.6 -112.0 46.6
#>   No. points: 74
#>   Properties: NULL

lint input geojson

For most functions, you can lint your input geojson data to make sure it is proper geojson. We use the javascript library geojsonhint. See the lint parameter where available.

Good GeoJSON

dat <- '{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "population": 200
      },
      "geometry": {
        "type": "Point",
        "coordinates": [10.724029, 59.926807]
      }
    },
      {
      "type": "Feature",
      "properties": {
        "population": 600
      },
      "geometry": {
        "type": "Point",
        "coordinates": [10.715789, 59.904778]
      }
    }
  ]
}'
lawn_extent(dat)
#> [1] 10.71579 59.90478 10.72403 59.92681

Bad GeoJSON

dat <- '{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "population": 200
      },
      "geometry": {
        "type": "Point"
      }
    },
      {
      "type": "Feature",
      "properties": {
        "population": 600
      },
      "geometry": {
        "type": "Point",
        "coordinates": [10.715789, 59.904778]
      }
    }
  ]
}'
lawn_extent(dat, lint = TRUE)

#> Error: Line 1 - "coordinates" member required

view

lawn includes a tiny helper function for visualizing geojson.

view(lawn_data$points_average)
map1

map1

Here, we sample at random two points from the same dataset just viewed.

lawn_sample(lawn_data$points_average, 2) %>% view()
map1

map1