Reputation: 339
I'm trying to convert a regular 1-degree by 1-degree geographic grid to polygons while maintaining the data associated with each grid point using the R sf package.
Example code:
library(tidyverse)
library(sf)
library(sfheaders)
library(sfheaders)
# latitude
lldata <- tibble(lat=as.numeric(rep(seq(40,49.5),10)))
# Longitude + add data
lldata <- lldata %>%
group_by(lat) %>%
mutate(lon = -90 + row_number()-1,
data = runif(1))
#Plot the grid as points
lldata %>%
ggplot() +
geom_point(aes(x=lon,y=lat,color=data))
# Attempt #1
#https://stackoverflow.com/questions/48383990/convert-sequence-of-longitude-and-latitude-to-polygon-via-sf-in-r
lldata %>% arrange(lat,-lon) %>%
st_as_sf(coords = c("lon", "lat"), crs = 4326) %>%
summarise(geometry = st_combine(geometry)) %>%
st_cast("POLYGON") %>%
ggplot() +
geom_sf()
# Also tried
poly <- st_sf(st_sfc(st_make_valid(st_polygon(list(as.matrix(lldata))))), crs = 4326)
# error that the polygon is not closed
# Attempt #2
# https://stackoverflow.com/questions/52669779/convert-sets-of-spatial-coordinates-to-polygons-in-r-using-sf/52671103
sf <- sfheaders::sf_polygon(
obj = lldata
, x = "lon"
, y = "lat"
)
# Same result as above
sf %>%
ggplot() +
geom_sf()
I'm expecting a polygon whose boundaries are defined by the regular grid but the boundaries of each polygon are not being closed. Is there a simple solution in the SF package I'm missing?
Also, when creating the polygon, I'd like for the variable "data" to be associated with each polygon. I have not made it that far, however.
Upvotes: 0
Views: 1320
Reputation: 1165
Using sf::st_make_grid
:
library(tidyverse)
library(sf)
lldata <- tibble(lat = as.numeric(rep(seq(40, 49.5), 10))) %>%
group_by(lat) %>%
mutate(lon = -90 + row_number() - 1,
data = runif(1)) %>%
ungroup() %>%
st_as_sf(coords = c("lon", "lat"))
lldata_poly <- lldata %>%
st_make_grid(cellsize = 1, offset = c(-90.5, 39.5)) %>%
st_as_sf() %>%
st_join(lldata)
# plot
ggplot() +
geom_sf(data = lldata_poly, aes(fill = data)) +
geom_sf(data = lldata)
# export
write_sf(lldata_poly, "~/grid.shp")
You can adjust the offset depending of what you want (centers or corners)
Upvotes: 1
Reputation: 1382
Probably the most convenient way to do this is to use stars, stars objects can be plotted directly with ggplot or you can make spatial polygons out of it:
library(tidyverse)
library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1; sf_use_s2() is TRUE
library(sfheaders)
require(stars)
#> Loading required package: stars
#> Loading required package: abind
# latitude
lldata <- tibble(lat=as.numeric(rep(seq(40,49.5),10)))
# Longitude + add data
lldata <- lldata %>%
group_by(lat) %>%
mutate(lon = -90 + row_number()-1,
data = runif(1))
ggplot()+geom_stars(data=st_as_stars(lldata, dims = c('lon','lat')))
st_as_stars(lldata, dims = c('lon','lat')) %>% st_as_sf(as_points=F)
#> Simple feature collection with 100 features and 1 field
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: -90.5 ymin: 39.5 xmax: -80.5 ymax: 49.5
#> CRS: NA
#> First 10 features:
#> data geometry
#> 1 0.5560062 POLYGON ((-90.5 49.5, -89.5...
#> 2 0.5560062 POLYGON ((-89.5 49.5, -88.5...
#> 3 0.5560062 POLYGON ((-88.5 49.5, -87.5...
#> 4 0.5560062 POLYGON ((-87.5 49.5, -86.5...
#> 5 0.5560062 POLYGON ((-86.5 49.5, -85.5...
#> 6 0.5560062 POLYGON ((-85.5 49.5, -84.5...
#> 7 0.5560062 POLYGON ((-84.5 49.5, -83.5...
#> 8 0.5560062 POLYGON ((-83.5 49.5, -82.5...
#> 9 0.5560062 POLYGON ((-82.5 49.5, -81.5...
#> 10 0.5560062 POLYGON ((-81.5 49.5, -80.5...
Created on 2022-02-08 by the reprex package (v2.0.1)
Upvotes: 0