R SF – How to Append a Geometry Column to a Data Frame Using the R Package sf

rsf

I'm working with Debian 8 usin R 3.4 and the spatial package sf 0.9.4. I try to append a geometry column but cannot find the right iteration mode. The data table was generated from a SQL query and contains two columns for UTMX and UTMY coordinates representing the center of a cell.

head(
   tab.ds[tab.ds$rgn !='NN' & ! is.na(tab.ds$dens), 
          c('irow', 'icol','ux','uy','ndist','dens', 'rgn')])

##    irow icol     ux      uy     ndist     dens rgn
## 50   10    3 316114 6028314 11134.732 1.783611   D
## 56    4    3 316958 6050121  8137.872 3.267525   D
## 57    5    3 316817 6046494  4747.973 1.747866   C
## 58    6    3 316677 6042864  2281.063 1.329282   B
## 59    7    3 316536 6039231  3694.376 3.088088   B
## 60    8    3 316395 6035595  6161.736 1.869873   C

Where the columns repersenting:

  • icol – Raster column index,
  • irow – Raster row index,
  • ux – UTM-X component of the cell center,
  • uy – UTM-Y component of the cell center,
  • ndis – the minimal distance to an obstacle,
  • dens – the density of an spieces and
  • rgn – the regin class within the obstacle lies.

But for a test procedure the table:

 # Cell width
 RST.WIDTH = 123

 tab.ds <- data.frame( ux = c( 1,  2, -3), 
                       uy = c(-1, -2, -3))

should work. I want to append a geometry column for each table row represented by the cell polygon.
To generate the polygon I've written a function which looks like this:

sf.rect.xywh <- function(x, y, w, h) {
    # using the half cellsize
    dw <- w/2;  dh <- h/2
    # create the corner points
    nw.x <- x - dw; nw.y <- y + dh;
    ne.x <- x + dw; ne.y <- y + dh;
    se.x <- x + dw; se.y <- y - dh;
    sw.x <- x - dw; sw.y <- y - dh;
    # use vectors to arrange them in a matrix
    cx <- c(nw.x, ne.x, se.x, sw.x, nw.x);
    cy <- c(nw.y, ne.y, se.y, sw.y, nw.y);
    # create the coordinate matrix 
    coord <- matrix(c(cx, cy), ncol=2, nrow = 5 )
    # create the polygon 
    poly <- st_polygon(list(coord))
    # give back the results
    return(poly)
}

#Test
sf.rect.xywh(10,-10, 4, 4)

## POLYGON ((8 -8, 12 -8, 12 -12, 8 -12, 8 -8))

Which works fine and gives me a closed polygon. As I understand, I've to convert the data frame into a sf object using but don't know, how to do it. If I try to append a create polygon column

  # Number of rows       
  N<-nrow(tab.ds)
  
  # add column geom
  tab.ds$geom<-sf.rect.xywh(tab.ds$ux, 
                            tab.ds$uy, 
                            w=rep(RST.WIDTH,N),
                            h=rep(RST.WIDTH,N))

I get:

MtrxSet(x, dim, type = "POLYGON", needClosed = TRUE) polygons not (all) closed. 

I suppose, that I need to address a row wise iteration. What is the right code to do that?

Best Answer

I will assume that you can use dplyr if not you can adapt to base R. Here's a solution

library(sf)
library(dplyr)

RST_WIDTH  <- 123

tab_ds <- data.frame(ux = c( 1,  2, -3),
                     uy = c(-1, -2, -3)) %>%
  mutate(w = RST_WIDTH, h = RST_WIDTH)

tab_ds %>%
  rowwise() %>%
  mutate(geometry = list(sf.rect.xywh(ux, uy, w, h))) %>%
  st_as_sf(sf_column_name = "geometry")

## Simple feature collection with 3 features and 4 fields
## geometry type:  POLYGON
## dimension:      XY
## bbox:           xmin: -64.5 ymin: -64.5 xmax: 63.5 ymax: 60.5
## CRS:            NA
## # A tibble: 3 x 5
## # Rowwise: 
##      ux    uy     w     h                                geometry
##   <dbl> <dbl> <dbl> <dbl>                               <POLYGON>
## 1     1    -1   123   123 ((-60.5 60.5, 62.5 60.5, 62.5 -62.5, -…
## 2     2    -2   123   123 ((-59.5 59.5, 63.5 59.5, 63.5 -63.5, -…
## 3    -3    -3   123   123 ((-64.5 58.5, 58.5 58.5, 58.5 -64.5, -…

Hope it helps

Related Question