Aggregate POLYGONs to MULTIPOLYGONs and keep data.frame
Asked Answered
S

3

11

I have a sf object of POLYGON geometry type. I would like to aggregate these polygons into MULTIPOLYGONs using grouping attribute (group_attr) and join a new MULTIPOLYGON object with a attribute table. So, as a result, I will have a sf object with two rows and three columns (group_attr, second_attr, geometry). I've already tried to used st_cast - it works well on sfc objects, but not on sf objects. Is it possible to do this using sf package?

p1 <- rbind(c(0,0), c(1,0), c(3,2), c(2,4), c(1,4), c(0,0))
pol1 <-st_polygon(list(p1))
p2 <- rbind(c(3,0), c(4,0), c(4,1), c(3,1), c(3,0))
pol2 <-st_polygon(list(p2))
p3 <- rbind(c(4,0), c(4,1), c(5,1), c(5,0),c(4,0))
pol3 <-st_polygon(list(p3))
p4 <- rbind(c(3,3), c(4,2), c(4,3), c(3,3))
pol4 <-st_polygon(list(p4))

d <- data.frame(group_attr = c(1, 1, 2, 2), 
                second_attr = c('forest', 'forest', 'lake', 'lake'))
d$geometry <- st_sfc(pol1, pol2, pol3, pol4)
df<- st_as_sf(d)
plot(df)
df

Simple feature collection with 4 features and 2 fields
geometry type:  POLYGON
dimension:      XY
bbox:           xmin: 0 ymin: 0 xmax: 5 ymax: 4
epsg (SRID):    NA
proj4string:    NA
  group_attr second_attr                       geometry
1          1      forest POLYGON((0 0, 1 0, 3 2, 2 4...
2          1      forest POLYGON((3 0, 4 0, 4 1, 3 1...
3          2        lake POLYGON((4 0, 4 1, 5 1, 5 0...
4          2        lake  POLYGON((3 3, 4 2, 4 3, 3 3))

enter image description here

Sardonyx answered 16/3, 2017 at 18:56 Comment(0)
S
6

A new approach based on https://github.com/r-spatial/sf/issues/634#issuecomment-365151794:

library(dplyr)

df_new <- df %>%
  group_by(group_attr) %>%
  summarise_all(first) 
df_new

Simple feature collection with 2 features and 2 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: 0 ymin: 0 xmax: 5 ymax: 4
epsg (SRID):    NA
proj4string:    NA
# A tibble: 2 x 3
  group_attr second_attr                                                        geometry
       <dbl> <fct>                                                        <MULTIPOLYGON>
1       1.00 forest      (((3 0, 3 1, 4 1, 4 0, 3 0)), ((0 0, 1 4, 2 4, 3 2, 1 0, 0 0)))
2       2.00 lake                  (((4 0, 4 1, 5 1, 5 0, 4 0)), ((3 3, 4 2, 4 3, 3 3)))
Sardonyx answered 15/2, 2018 at 16:22 Comment(2)
This worked great for me. What does having the function "first" for summarizing do?Soluble
I'm not sure why they've used it here, but dplyr::first is a shortcut for targeting the first item in a vector, equivalent to [[1]]. This will be passed to summarise_all as the .funs argument, maybe they've used it to control the naming of the columns. Be interesting to investigate further.Guarded
F
4

or:

> aggregate(df, list(df$second_attr), function(x) x[1])
Simple feature collection with 2 features and 3 fields
Attribute-geometry relationship: 0 constant, 2 aggregate, 1 identity
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: 0 ymin: 0 xmax: 5 ymax: 4
epsg (SRID):    NA
proj4string:    NA
  Group.1 group_attr second_attr                       geometry
1  forest          1      forest MULTIPOLYGON(((3 0, 3 1, 4 ...
2    lake          2        lake MULTIPOLYGON(((4 0, 4 1, 5 ...
Fact answered 3/6, 2017 at 9:2 Comment(2)
Thanks - this works cleanly. I will note that I had to use a slight variation on this emp <- st_is_empty(df); aggregate(df[!emp,], by=list(df$second_attr[!emp]), FUN=function(x) x[1]) because I had some empty polygons. After much hair tearing, I figured out I needed to exclude them first.Loquacity
if you believe that is an issue, please raise it as issue on the sf github page.Fact
S
1

Very hacky (or naive) approach:

attr_table <- df %>% 
        as_data_frame() %>% 
        select(-geometry) %>% 
        unique()

new_df <- df %>% 
        group_by(group_attr) %>% 
        summarise() %>% 
        as.data.frame(.) %>% 
        left_join(., attr_table, by='group_attr')   %>% 
        st_as_sf()

new_df

Simple feature collection with 2 features and 2 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: 0 ymin: 0 xmax: 5 ymax: 4
epsg (SRID):    NA
proj4string:    NA
  group_attr second_attr                       geometry
1          1      forest MULTIPOLYGON(((3 0, 3 1, 4 ...
2          2        lake MULTIPOLYGON(((4 0, 4 1, 5 ...
Sardonyx answered 17/3, 2017 at 15:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.