Reputation: 727
I have clusters of points from different datasets collected in different geographical regions. I'd like to plot the spatial extent of each region on a map, for which I need a single polygon per region. I can find commands to convert points to polygons by "connecting the dots", but none by drawing an outline (the geometric method isn't terribly important since this is just for plotting). Here's a reprex to generate a simplified dataframe like the one I'm using, for points in Norway, Alaska, and the continental US:
nor_lat <- c(72.117, 71.05, 71.717, 71.167, 71.817, 72.333, 71.25, 70.917,
70.85, 70.933)
nor_lon <- c(33.217, 30.333, 26.3, 22.333, 22.333, 22.333, 18.517, 20.133,
21.333, 19.917)
us_lat <- c(41.283333, 41, 40.95, 40.95, 38.683333, 40.783333, 40.733333,
40.516667, 38.566667, 41.266667)
us_lon <- c(-71.116667, -70.733333, -70.583333, -70.483333, -74.816667,
-70.5, -70.566667, -70.266667, -74.85, -71.366667)
ak_lat <- c(58.015, 57.67167, 57.33833, 56.685, 56.99333, 57.31667, 57.65,
57.99667, 58.32167, 58.33333)
ak_lon <- c(-158.31667, -158.36, -158.41, -159.76, -159.72333, -159.66333,
-159.64167, -159.605, -159.54, -160.72167)
nor_dat <- data.frame(lat=nor_lat, lon=nor_lon)
us_dat <- data.frame(lat=us_lat, lon=us_lon)
ak_dat <- data.frame(lat=ak_lat, lon=ak_lon)
nor_dat$region <- "nor"
us_dat$region <- "us"
ak_dat$region <- "ak"
dat <- rbind(nor_dat, us_dat, ak_dat)
For the object dat
, I'd like to generate a simple polygon around the points in each region
, using sf if possible. (I'm not too worried about figuring out how to iterate over the regions, but I can't even figure out how to draw a polygon around one set of points!)
Upvotes: 0
Views: 5303
Reputation: 4140
library(sf)
library(dplyr)
hulls <- dat %>%
st_as_sf(coords = c("lon", "lat")) %>%
group_by(region) %>%
summarize(geometry = st_union(geometry)) %>%
st_convex_hull()
plot(hulls)
Upvotes: 3
Reputation: 4652
One approach using sf
and dplyr
for "geocomputation" and filtering, tmap
and tmaptools
for visualization.
Please find the following reprex.
Reprex
dataframe
"dat" into a sf
objectlibrary(sf)
library(dplyr)
library(tmap)
library(tmaptools)
sf_use_s2(TRUE)
dat_sf <- st_as_sf(dat, coords = c("lon", "lat"), crs = 4326)
conv_nor <- st_simplify(st_buffer(st_convex_hull(st_union(st_geometry(filter(dat_sf, region == "nor")))), dist = 15000), dTolerance = 5000)
conv_us <- st_simplify(st_buffer(st_convex_hull(st_union(st_geometry(filter(dat_sf, region == "us")))), dist = 15000), dTolerance = 5000)
conv_ak <- st_simplify(st_buffer(st_convex_hull(st_union(st_geometry(filter(dat_sf, region == "ak")))), dist = 15000), dTolerance = 5000)
tm_shape(dat_sf)+
tm_dots(size = 0.2, col = "black", shape = 21, alpha = 0.3)+
tm_shape(conv_nor)+
tm_borders(col = "gray", lwd = 2)+
tm_shape(conv_us)+
tm_borders(col = "blue", lwd = 2)+
tm_shape(conv_ak)+
tm_borders(col = "gray", lwd = 2)+
tm_layout(frame = FALSE)
tm_shape(filter(dat_sf, region == "nor"), bbox = bb(conv_nor, ext = 1))+
tm_dots(size = 0.5, alpha = 0.5)+
tm_shape(conv_nor)+
tm_borders(col = "gray", lwd = 2)+
tm_layout(frame = FALSE, title = "'nor' area",
title.size = 1.5, title.position = c(0.85, "bottom"))
tm_shape(filter(dat_sf, region == "us"), bbox = bb(conv_us, ext = 1))+
tm_dots(size = 0.5, alpha = 0.5)+
tm_shape(conv_us)+
tm_borders(col = "gray", lwd = 2)+
tm_layout(frame = FALSE, title = "'us' area",
title.size = 1.5, title.position = c(0., "top"))
tm_shape(filter(dat_sf, region == "ak"), bbox = bb(conv_ak, ext = 1))+
tm_dots(size = 0.5, alpha = 0.5)+
tm_shape(conv_ak)+
tm_borders(col = "gray", lwd = 2)+
tm_layout(frame = FALSE, title = "'ak' area",
title.size = 1.5, title.position = c(0.75, "top"))
Finally, if you want some contextual background, you can use the tmap_mode("view")
which call leaflet
- apparently you work on the marine environment ;-)
tmap_mode("view")
#> tmap mode set to interactive viewing
tm_shape(filter(dat_sf, region == "nor"), bbox = bb(conv_nor, ext = 1))+
tm_dots(size = 0.5, alpha = 0.5)+
tm_shape(conv_nor)+
tm_borders(col = "gray", lwd = 2)+
tm_layout(frame = FALSE, title = "'nor' area",
title.size = 1.5, title.position = c(0.85, "bottom"))
tm_shape(filter(dat_sf, region == "us"), bbox = bb(conv_us, ext = 1))+
tm_dots(size = 0.5, alpha = 0.5)+
tm_shape(conv_us)+
tm_borders(col = "gray", lwd = 2)+
tm_layout(frame = FALSE, title = "'us' area",
title.size = 1.5, title.position = c(0., "top"))
tm_shape(filter(dat_sf, region == "ak"), bbox = bb(conv_ak, ext = 1))+
tm_dots(size = 0.5, alpha = 0.5)+
tm_shape(conv_ak)+
tm_borders(col = "gray", lwd = 2)+
tm_layout(frame = FALSE, title = "'ak' area",
title.size = 1.5, title.position = c(0.75, "top"))
tmap_mode("plot")
#> tmap mode set to plotting
Created on 2021-10-20 by the reprex package (v2.0.1)
Upvotes: 1