Unfortunately it's rather difficult to use maps
data to spatially filter points, because the data is really for plotting and not so much for doing spatial operations with. Luckily, it's fairly easy to use the sf
package to do this kind of spatial work.
- First I get a New Zealand boundary from the
rnaturalearth
package, which is a convenient source of country borders. I do a few transformations to keep only the largest three polygons in the shapefile, since otherwise we'd plot a lot of far flung islands that likely aren't relevant to this map.
- Then I generate some random points around New Zealand. You can see that the
tibble
is just a column of longitudes and a column of latitudes. We turn this into point geometries with st_as_sf
and plot it, to show what it looks like.
- Last, we can use
st_within
to check for each point whether or not it is inside the nz
boundary. st_within
returns a list of indices of polygons that the point is within for each point, so we can use lengths
to get the result we want. Here anything that is 0
is not within the boundary and anything that is 1
is within the boundary. Plotting with this new on_land
attribute shows that offshore points are appropriately coloured.
library(tidyverse)
library(sf)
#> Linking to GEOS 3.6.1, GDAL 2.2.3, proj.4 4.9.3
library(rnaturalearth)
nz <- ne_countries(country = "New Zealand", returnclass = "sf", scale = "large") %>%
st_cast("POLYGON") %>%
mutate(area = st_area(geometry)) %>%
top_n(3, area)
#> Warning in st_cast.sf(., "POLYGON"): repeating attributes for all sub-
#> geometries for which they may not be constant
points <- tibble(
x = runif(1000, st_bbox(nz)[1], st_bbox(nz)[3]),
y = runif(1000, st_bbox(nz)[2], st_bbox(nz)[4])
)
points
#> # A tibble: 1,000 x 2
#> x y
#> <dbl> <dbl>
#> 1 167. -44.5
#> 2 175. -40.9
#> 3 177. -43.8
#> 4 167. -44.8
#> 5 173. -39.3
#> 6 173. -42.1
#> 7 176. -41.9
#> 8 171. -44.9
#> 9 173. -41.2
#> 10 174. -39.5
#> # ... with 990 more rows
points <- st_as_sf(points, coords = c("x", "y"), crs = 4326)
plot(nz$geometry, col = "red")
plot(points, pch = 19, cex = 1, add = TRUE)

points <- points %>% mutate(on_land = lengths(st_within(points, nz)))
#> although coordinates are longitude/latitude, st_within assumes that they are planar
plot(nz$geometry, col = "red")
plot(points, pch = 19, cex = 1, add = TRUE)

Created on 2018-05-02 by the reprex package (v0.2.0).