Search code examples
rspatialr-sf

Aggregating values of overlapping polygons within a layer using the origins value from st_intersection


I would like to take a spatial layer with overlapping polygons and transform it so that a layer without any overlaps is created, and the attributes of the overlapping polygons aggregated as a list, or a sum (will vary depending on the field and goal of analysis). Based on these posts https://github.com/r-spatial/sf/issues/1230 , summarise attributes from sf::st_intersection() where geometries overlaps I think that I should be able to do this using the origins field created when st_intersection() is used with a single input.

An example with some dummy data:

set.seed(123)
p1 = st_cast(st_sfc(st_multipoint(cbind(runif(10),runif(10)))),"POINT")

b1 =st_buffer(p1, .15)

b1d = data.frame(id=1:10, class=rep(c("high", "low"), times=5), value= rep(c(10,5),times=5))
b1d$geometry = b1
b1d = st_as_sf(b1d)


b1d_intersect <- st_intersection(b1d)%>% 
  mutate(id_int=seq(from=1, to=nrow(.), by=1)) %>% 
  st_collection_extract()

ggplot(b1d)+geom_sf(aes(fill=class), alpha=0.5)

ggplot(b1d_intersect)+geom_sf(aes(fill=class), alpha=0.5) 

In my desired output the attributes of each polygon would aggerate overlapping attribute values, something like:

b1d_intersect_values <- b1d_intersect %>% 
  group_by(rownames(.)) %>% 
  summarise(Class_List=paste0(class, collapse = "; "), value_sum=sum(value))

but that actually works by linking back to the original b1d layer using the origins field? I feel like I need to use map() somewhere in there.

I've also tried to tackle it using st_join, but that doesn't work quite right as it is assigning multiple classes for polygons where n.overlaps=1, and it also seems as though would take longer than using an index when applied to large data sets as it would require the additional spatial processing step with st_join.

b1d_intersect_values_2 <- st_join(b1d_intersect, b1d) %>% 
  group_by(id_int, n.overlaps) %>% 
  summarise(class_list=paste0((class.y),collapse="; "), value_sum=sum(value.y))

Any suggestions on how to proceed would be appreciated.


Solution

  • Figured it out eventually, answering myself so nobody wastes time or effort, and in case helpful to anyone else.

    b1d_intersect_values <- b1d_intersect %>% 
      mutate(class_list=map_chr(origins,  ~ paste0(class[.], collapse = "; ")),
             value_sum=map_dbl(origins,  ~ sum(value[.])))
    
    
    
    
    ggplot(b1d_intersect_values)+geom_sf(aes(fill=class_list, alpha=value_sum))