2

I am trying to create a polygon from a coordinate dataframe. I have the minimum and maximum x-y coordinate information. But, I am getting the following error. How can this be fixed?

library(tidyverse)
library(sf)
lon = c(756065.70, 757428.78)
lat = c(4074435.19,4075144.12)

Poly_Coord_df = data.frame(lon, lat)

Poly = Poly_Coord_df %>% 
  st_as_sf(coords = c("lon", "lat"), crs = 32611) %>% 
  summarise((geometry = st_combine(geometry))) %>% 
  st_cast("POLYGON")

Error

Error in h(simpleError(msg, call)) : 
  error in evaluating the argument 'x' in selecting a method for function 'plot': polygons require at least 4 points

2 Answers 2

5

In the specific context you describe - having top right and bottom left corner of your desired polygon - you may be able to get by with sf::st_bbox(). It returns the bounding box of an object, in your case of the Poly_Coords_df data frame (as intepreted in context of EPSG:32611).

poly <- Poly_Coord_df %>% 
  st_as_sf(coords = c("lon", "lat"), 
           crs = 32611) %>% 
  st_bbox() %>% 
  st_as_sfc()
1

You've only got two points so you need to construct five to complete a box.

I don't understand what all that pipeline is supposed to do, the simplest and most direct way is to use st_polygon and feed it a list of a matrix which has five rows and two columns by taking the elements from your data frame:

> pol = st_polygon(
     list(
       cbind(
         Poly_Coord_df$lon[c(1,2,2,1,1)], 
         Poly_Coord_df$lat[c(1,1,2,2,1)])
       )
    )

which returns:

POLYGON ((756065.7 4074435, 757428.8 4074435, 757428.8 4075144, 756065.7 4075144, 756065.7 4074435))

You probably then want to add the coordinate system and convert to an sfc:

polc = st_sfc(pol, crs=32611)


> polc
Geometry set for 1 feature 
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: 756065.7 ymin: 4074435 xmax: 757428.8 ymax: 4075144
Projected CRS: WGS 84 / UTM zone 11N
POLYGON ((756065.7 4074435, 757428.8 4074435, 7...

How it works - the sf_polygon function needs a matrix with two columns, with points in rows, the first point and the last point being the same to complete the polygon. For example to construct a "unit square" polygon between (0,0) and (1,1) you could make the matrix by making the columns and combining with cbind:

> cbind(c(0,1,1,0,0), c(0,0,1,1,0))
     [,1] [,2]
[1,]    0    0
[2,]    1    0
[3,]    1    1
[4,]    0    1
[5,]    0    0

And you can feed that into st_polygon, wrapping it in a list because polygons can be complex features with more than one "ring".

> st_polygon(list(cbind(c(0,1,1,0,0), c(0,0,1,1,0))))
POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))

Plotting that shows a square:

enter image description here

For your specific data frame, you get the latitudes as a vector like this:

> Poly_Coord_df$lat
[1] 4074435 4075144

and if you get them in the right order by subsetting:

> Poly_Coord_df$lat[c(1,1,2,2,1)]
[1] 4074435 4074435 4075144 4075144 4074435

that gets you the latitudes for making a polygon. A similar subset gets them in the right order for the longitude, and then binding them together you can feed them to sf_polygon.

2
  • Can you please briefly explain what does Poly_Coord_df$lon[c(1,2,2,1,1)] mean? Jul 14, 2021 at 21:59
  • 1
    "briefly" it is standard R data frame column extraction and subsetting, which is normally taught in first steps in R. Not sure how you missed that.
    – Spacedman
    Jul 15, 2021 at 8:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.