R sf::st_convex_hull() losing sf class on data with multiple groups

Viewed 217

I am trying to create a 95% minimum convex polygon using sf in R. My code works fine as long as I only group my data on 1 variable, but when I group on two variables, the output loses its sf class and becomes a grouped_df instead.

Here is a toy dataset as an example

library(dplyr) 
set.seed(12)
toy <- tibble::tibble(
    ID = rep(c(1,2), each = 10),
    year = rep(c(1,2), 10),
    lat = runif(20, 1, 10),
    long = runif(20, 1, 10)
  ) %>%
    sf::st_as_sf(., coords = c("long", "lat")) 
toy %>%
  group_by(ID) %>% 
  summarize(.groups = "keep") %>% 
  mutate(cent = sf::st_centroid(geometry)) %>%
  sf::st_cast(to = "POINT") %>%  
  mutate(dist = sf::st_distance(geometry, cent, by_element = TRUE)) %>% 
  filter(dist <= quantile(dist, .95)) %>% 
  summarize()  %>%
  sf::st_convex_hull() %>%
  class()

This gives the output I want. But when I try to group by two variables, the result loses the sf class.

toy %>%
  group_by(ID, year) %>% 
  summarize(.groups = "keep") %>% 
  mutate(cent = sf::st_centroid(geometry)) %>%
  sf::st_cast(to = "POINT") %>%  
  mutate(dist = sf::st_distance(geometry, cent, by_element = TRUE)) %>% 
  filter(dist <= quantile(dist, .95)) %>% 
  summarize()  %>%
  sf::st_convex_hull() %>%
  class

Is there something in my code keeping me from being able to group on two variables?

1 Answers

It's because the second summarize is regrouping on ID. You need a .groups = "keeps" there to pass the same grouping through and then convert back to an sf object. Alternatively you could create a grouping variable mutate(grp = paste0(ID, year)) and do group_by(grp) .

toy %>%
  group_by(ID, year) %>% 
  summarize(.groups = "keep") %>% 
  mutate(cent = sf::st_centroid(geometry)) %>%
  sf::st_cast(to = "POINT") %>%  
  mutate(dist = sf::st_distance(geometry, cent, by_element = TRUE)) %>% 
  filter(dist <= quantile(dist, .95)) %>% 
  summarize(.groups = "keep")  %>%
  sf::st_convex_hull() %>%
  st_sf()

Related