Convert sequence of longitude and latitude to polygon via sf in R

▼魔方 西西 提交于 2019-11-27 22:30:49

问题


I have five longitude and latitude that form a shape like this.

df <- c(order=1:5,
        lon=c(119.4,119.4,119.4,119.5,119.5), 
        lat=c(-5.192,-5.192,-5.187,-5.187,-5.191))

How could I easily convert them into an sf polygon data frame using sf package like this?

## Simple feature collection with 1 feature and 0 fields
## geometry type:  POLYGON
## dimension:      XY
## bbox:           xmin: 119.4 ymin: -5.192 xmax: 119.5 ymax: -5.187
## epsg (SRID):    4326
## proj4string:    +proj=longlat +datum=WGS84 +no_defs
## geometry
## 1 POLYGON ((119.4 ...

回答1:


The equivalent as @Yo B. answer but with sf

library(sf)
df <- data.frame(lon=c(119.4,119.4,119.4,119.5,119.5), 
                 lat=c(-5.192,-5.192,-5.187,-5.187,-5.191))

# You need first to close your polygon 
# (first and last points must be identical)
df <- rbind(df, df[1,])

poly <- st_sf(st_sfc(st_polygon(list(as.matrix(df)))), crs = 4326)
poly

## Simple feature collection with 1 feature and 0 fields
## geometry type:  POLYGON
## dimension:      XY
## bbox:           xmin: 119.4 ymin: -5.192 xmax: 119.5 ymax: -5.187
## epsg (SRID):    4326
## proj4string:    +proj=longlat +datum=WGS84 +no_defs
##   st_sfc.st_polygon.list.as.matrix.df....
## 1          POLYGON ((119.4 -5.192, 119...

edit to answer a question in the comments

See the main sf vignette for a clear and detailed explanation of sf, sfc and sfg objects summarized as :

The three classes used to represent simple features are:

  • sf, the table (data.frame) with feature attributes and feature geometries, which contains
  • sfc, the list-column with the geometries for each feature (record), which is composed of
  • sfg, the feature geometry of an individual simple feature.

The st_sfc function builds only the geometry column (which is a list of polygons - here with only one polygon). The "c" in sfc stands for "column". The function st_sf builds a full sf object (which has also a data.frame class) which his a data frame with a geometry column. In the given example there is no data attached to the polygon (no attributes). You can attach data by building a data.frame :

poly <- st_sf(data.frame(landuse = "Forest", 
                         size = 23 , 
                         st_sfc(st_polygon(list(as.matrix(df))))), 
              crs = 4326)
poly
## ## Simple feature collection with 1 feature and 2 fields
## geometry type:  POLYGON
## dimension:      XYZ
## bbox:           xmin: 1 ymin: 119.4 xmax: 5 ymax: 119.5
## epsg (SRID):    4326
## proj4string:    +proj=longlat +datum=WGS84 +no_defs
## landuse size                       geometry
## 1  Forest   23 POLYGON Z ((1 119.4 -5.192,...

You can then extract each of these elemnts form the spatial object and check their class :

Full sf object : a data.frame with a sfc geometry column

class(poly)
## "sf"         "data.frame"

Third column extracted as a list : sfc object

class(poly[[3]])
## "sfc_POLYGON" "sfc"    

First element of the geometry column : an sfg polygon object

class(poly[[3]][[1]])
## "XY"      "POLYGON" "sfg"  



回答2:


I saw that this question is coming up in search results, so I thought I'd provide a more flexible method of creating polygons in sf from a series of lat and lon coordinates.

st_as_sf has an argument coords that will take points given as coordinate columns in a data frame and convert those columns to sf POINT geometries. Then, because sf works well with dplyr, we can st_combine the points into a MULTIPOINT and st_cast to convert to POLYGON. Compared to "manual" construction with st_polygon, this has the advantage that we don't have to think so carefully about closing the ring or about the right level of nested lists to pass to the constructor, and that if we have more than one polygon in a list of coordinates we can use group_by to create all the polygons at once.

N.B. Technically you can do this with do_union=FALSE inside of summarise, but I think that this syntax is a bit clearer and more similar to normal summarise.

df <- data.frame(
  lon = c(119.4, 119.4, 119.4, 119.5, 119.5),
  lat = c(-5.192, -5.192, -5.187, -5.187, -5.191)
)
library(tidyverse)
library(sf)
#> Linking to GEOS 3.6.1, GDAL 2.2.3, proj.4 4.9.3
polygon <- df %>%
  st_as_sf(coords = c("lon", "lat"), crs = 4326) %>%
  summarise(geometry = st_combine(geometry)) %>%
  st_cast("POLYGON")
polygon
#> Simple feature collection with 1 feature and 0 fields
#> geometry type:  POLYGON
#> dimension:      XY
#> bbox:           xmin: 119.4 ymin: -5.192 xmax: 119.5 ymax: -5.187
#> epsg (SRID):    4326
#> proj4string:    +proj=longlat +datum=WGS84 +no_defs
#>                         geometry
#> 1 POLYGON ((119.4 -5.192, 119...

plot(polygon)

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




回答3:


I don't know "sf", but just in case you meant "sp", here is the complete construction of a SPDF

df <- data.frame(lon=c(119.4,119.4,119.4,119.5,119.5), 
             lat=c(-5.192,-5.192,-5.187,-5.187,-5.191))

require(sp)
spdf <- SpatialPolygonsDataFrame(
  SpatialPolygons(
    Srl=list(
      Polygons(srl=list(
        Polygon(coords=df)
      ), ID=1)
    )
  ),
  data=data.frame(a=1)
)

plot(spdf)



回答4:


library(sfheaders) on CRAN from 20191004 can take a data.frame and convert it to sf objects

library(sf)
library(sfheaders)

df <- data.frame(
  lon = c(119.4, 119.4, 119.4, 119.5, 119.5),
  lat = c(-5.192, -5.192, -5.187, -5.187, -5.191)
)

sfheaders::sf_polygon(
  obj = df
)
## given only two columns of data are in df there's no need to specify lon & lat arguments

# Simple feature collection with 1 feature and 1 field
# geometry type:  POLYGON
# dimension:      XY
# bbox:           xmin: 119.4 ymin: -5.192 xmax: 119.5 ymax: -5.187
# epsg (SRID):    NA
# proj4string:    
#   id                       geometry
# 1  1 POLYGON ((119.4 -5.192, 119...


来源:https://stackoverflow.com/questions/48383990/convert-sequence-of-longitude-and-latitude-to-polygon-via-sf-in-r

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!