I want to select features in a polygon shapefile on the basis of a selection criteria. In ArcGIS, one can do selection by attribute and then export selected data as shapefile. How can the same be done using the sf package in R?

   MultiPoly_Shp = st_read("path/MultiPoly_Shp.shp")
    List = c(33,35,36,37,50,54,57,59,60,61,62,63,64,66,67,69,70,71,76,78,80,90,93,97,98,99,100,101,102,106,107,108,111,112,115,118,119,120,121,122,123,124,125,127,128,147,148,152,153)
    Multipoly_Select = dplyr::select(MultiPoly_Shp$ID != List) 

# Export Multipoly_Select as .shp


Error in UseMethod("select") : 
  no applicable method for 'select' applied to an object of class "logical"
In addition: Warning message:
  longer object length is not a multiple of shorter object length

Maybe dplyr function drop or filter can also work, but I don't know which of these 3 functions best suits this purpose.

2 Answers 2


Using the sf and dplyr packages, you can select the desired features using filter and using the "not in"(! ... in ...) operator.


MultiPoly_Shp  %>%
  filter(!ID %in% List)

You can use which and %in% within a bracket index, so very un-tidy like.

( nc = st_read(system.file("shape/nc.shp", package="sf")) )

Here, we remove the elements in sc.

( sc <- sample(unique(nc$CNTY_ID), 10) )
  ( nc.sub <- nc[-which(nc$CNTY_ID %in% sc),] )

And, here we remove all elements except what is in sc.

( nc.sub <- nc[-which(!nc$CNTY_ID %in% sc),] )

The which function returns the position(s) of TRUE resulting from the statement. The "!" represents "not" so, the statement is functionally "x not in y". The minus remove indexed elements in the bracket.

And, if you want the tidy way you are looking for the filter function, not select which only subsets columns. Apparently, not-equal does not work nc %>% dplyr::filter(CNTY_ID != sc) but, nc %>% dplyr::filter(!CNTY_ID %in% sc) does. Curious.

  • Should I be worried about the warning message: longer object length is not a multiple of shorter object length that I get after running the dplyr::filter function? Jun 28, 2021 at 21:37
  • And actually, the tidy way suggested in your answer doesn't get rid of the unwanted IDs mentioned in the List variable. I simply did MultiPoly_Shp %>% dplyr::filter(ID != List). Jun 28, 2021 at 21:45
  • @Arthur_Morgan uh, that is exactly the same thing, just substituting different feature, column and variable names. nc %>% dplyr::filter(CNTY_ID != sc) There is an expectation that you provide a reproducible example and since you did not I put one in my answer. Jun 28, 2021 at 22:10
  • Yes, and when I did MultiPoly_Shp %>% dplyr::filter(ID != List), it did not work on getting rid of the unwanted IDs. Jun 28, 2021 at 22:11
  • 1
    Oh, I though you meant that your syntax worked. This filter syntax should work but, filter(CNTY_ID != sc) is not working where filter(CNTY_ID == sc) does work. Very odd. It does seem that the prudent tidy syntax here is dplyr::filter(!CNTY_ID %in% sc). Jun 28, 2021 at 22:23

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.