1

For each polygon in an sf object, I need to extract data on a single variable from all of the neighboring polygons. I have made a reprex below.

So far I have managed to get a list of the neighboring polygons using st_intersects,

demo(nc, ask = FALSE, verbose = FALSE)

nc <- nc %>% 
  mutate(polygon_id = row_number())

neighbors <- st_intersects(nc, nc)

For instance, polygon 5 (Northampton county) has the following neighbors:

neighbors[[5]]
[1]  5  6  9 16 28

I need the name from each of these neighbors (and do this for each polygon)

names(nc)
 [1] "AREA"       "PERIMETER"  "CNTY_"      "CNTY_ID"    "NAME"       "FIPS"       "FIPSNO"     "CRESS_ID"   "BIR74"      "SID74"      "NWBIR74"    "BIR79"     
[13] "SID79"      "NWBIR79"    "geom"       "polygon_id"

nc[c(6,9,16,28),5]
       NAME                           geom
6  Hertford MULTIPOLYGON (((-76.74506 3...
9    Warren MULTIPOLYGON (((-78.30876 3...
16  Halifax MULTIPOLYGON (((-77.33221 3...
28   Bertie MULTIPOLYGON (((-76.78307 3...

I am struggling to do two things:

  1. Remove 'the diagonal', that is the polygon itself (here, polygon 5) from its list of neighbors
  2. Extract the names of all its neighbors (Hertford, Warren, Halifax, and Bertie counties) into N character vectors, since the number of neighbors varies. Alternatively I can make do with pasting them into a single character vector separated by something that allows me to split them afterwards.
2
  • Your reproducible example isn't reproducible unless you show what packages you've used - looks like sf and possibly dplyr for mutate.
    – Spacedman
    Aug 19 '20 at 14:47
  • One question per question please.
    – Vince
    Aug 19 '20 at 15:56
2

This is a common list processing task - treat your neighborhood object as a list and use lapply like this to get the NAME elements of corresponding vectors in neighbors:

> namesof = lapply(neighbors, function(n){nc$NAME[n]})

giving:

> namesof[[1]]
[1] Ashe      Alleghany Wilkes    Watauga  
100 Levels: Alamance Alexander Alleghany Anson Ashe Avery Beaufort ... Yancey
> namesof[[2]]
[1] Ashe      Alleghany Surry     Wilkes   
100 Levels: Alamance Alexander Alleghany Anson Ashe Avery Beaufort ... Yancey

You can also use Map to get the result of a function on a list of elements, pretty much the same as lapply:

> namesof = Map(function(n){nc$NAME[n]}, neighbors)
> namesof[[1]]
[1] Ashe      Alleghany Wilkes    Watauga  
100 Levels: Alamance Alexander Alleghany Anson Ashe Avery Beaufort ... Yancey
> namesof[[2]]
[1] Ashe      Alleghany Surry     Wilkes   
100 Levels: Alamance Alexander Alleghany Anson Ashe Avery Beaufort ... Yancey

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