I create two buffer around points and want to intersect the two buffers by id (creating a doughnut) around each point. With st_intersection I can only manage to get all possible intersections, resulting in many more new polygons than I have points.


data    <- data.frame(id = paste0("ID_", 1:20), lon = runif(20, -10, 10), lat = runif(20, -10, 10))
data_sf <- st_as_sf(data,coords = c("lon", "lat"), crs = 4326) %>% st_transform(CRS("+proj=laea"))

bfr1 <- data_sf %>% st_buffer(150000)
bfr2 <- data_sf %>% st_buffer(450000)

inters1 <- st_intersection(bfr1, bfr2)

### I tried (with error)
bfr <- rbind(bfr1, bfr2)

hh <- bfr %>% 
  group_by(id) %>%
  summarise(geometry = st_intersection(geometry)) %>%

1 Answer 1


First of all, st_intersection will not result in what you want, as it will only return you the inner ring. This is the part where the two buffers are intersecting. What you want is st_difference: this will erase the inner buffer from the outer buffer resulting in a Donut. I hope I understood correctly that this is what you wanted. Keep in mind that when using st_difference you have to put the outer buffer first to be able to erase the smaller part from it.

Then there are two possible ways to solve your problem.

1. You can conduct a "filtering" of the difference result. As you said, a lot of differences are calculated, you could filter them by ID like this afterwards:

inters1 <- st_difference(bfr2, bfr1)    
final_inters1 <- inters1[which(inters1$id == inters1$id.1),]

2. You can apply the differencing beforehand by using lapply selecting every entity and applying the differencing to it. Thus, the other polygons will not be considered when doing the differencing. This is how I would code it, there are possibly nicer ways to do that - I am open for any suggestions.

inters <- lapply(1:nrow(data_sf), function(x){
  inters <- st_difference(bfr2[x,],bfr1[x,])
final_inters2 <- do.call(rbind.data.frame,inters)
  • Great, thanks! It is indeed st_difference. I like both ways!
    – SimeonL
    Apr 15, 2020 at 8:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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