Is there an sf-native (i.e. "correct") way of extracting everything except the geometry column from a simple features object? This works

df <- dplyr::select(as.data.frame(sf), -geometry)

but the select( , -geometry) step feels unnecessary. Also, it doesn't remove the geometry attributes.


5 Answers 5


To drop the geometry column, use st_drop_geometry():

nc <-  st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE)
nc_df2 <- nc %>% st_drop_geometry()
#> [1] "data.frame"

Before st_drop_geometry() was added to the sf package (in November, 2018), one could produce the same result using the st_set_geometry() function, like this:

nc <-  st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE)
#> [1] "sf"         "data.frame"

nc_df <- nc %>% st_set_geometry(NULL)
#> [1] "data.frame"

Set the st_geometry property to NULL.

nc <-  st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE)
## [1] "sf"         "data.frame"
st_geometry(nc) <- NULL
## [1] "data.frame"

Also (though this won't remove the attr(nc, "sf_column"):

nc <-  st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE)
  • I had tried nc$geometry <- NULL before, but your suggestion did the trick. Thank you. Jan 18, 2017 at 12:43
  • 1
    is there a piped version of this? sf %>% mutate(geometry = NULL) doesn't work
    – obrl_soil
    Apr 25, 2017 at 0:52
  • 3
    Maybe it's called "geom" and not "geometry"? (It's never going to be constant). Another way is ` x %>% st_set_geometry(NULL)`. Either of these might be in dev, not CRAN though I'm not checking carefully where I'm at locally.
    – mdsumner
    Apr 25, 2017 at 2:03
  • @mdsumner makes a great, indirect, point. Somebody has to actually write the method, it does not happen by magic. Since sf is a new object class in R many methods may not be available or not behave as expected. Dec 5, 2017 at 15:49
  • Is there a method that works for POINT or MULTIPOINT sf objects? When I try to do this with either of those I end up with a n × 0 df.
    – André.B
    May 5, 2020 at 20:30

why not simply select the columns that you would like?

as.data.frame(sf[,"some column name"])[,1]
  • This extracts a single column as a vector (sf$`some column name` is equivalent and simpler), and does not answer the question. Jul 17, 2020 at 22:54
  • well, you can index as much columns with this method as you like, so I do not really see why this should not solve the problem. In addition is it easier than the method suggested above.
    – joaoal
    Jul 22, 2020 at 19:52
  • 1. The problem was to extract the entire data.frame, not selected columns. This solution is not particularly well suited for this purpose, except for very small datasets, and certainly is not "sf-native". 2. I guess the simplicity of a method might be a matter of opinion, but st_set_geometry, st_drop_geometry and st_geometry are all mostly self-explanatory, and shorter than your method. Jul 22, 2020 at 20:15

as.data.frame(your_sf_object)[,-ncol(your_sf_object)] returns all the attribute columns except for its geometry. Also, use as.data.frame(your_sf_object)[,-8] if your 8th column is geometry.

If you prefer to use data.table rather than data.frame, you can use


or data.table(your_sf_object)[,-8,with=F] if your 8th column is geometry.

NOTE: This is my answer to an already old question, but time will come when I need this solution again but I forgot how I did it, so this is a good place to store the solution. Anyway, I got this solution from this thread. Sincerely, Yours Truly...

df <- df[,-geometry_column]

Or just df[,-geometry_column] if you don't want to create new object


df - your object

geometry_column - column where geometry is stored

  • Doesn't work on my end. Have you tested it? I do sf[, -sf$geometry] and get Error in Ops.sfc(grid.sf$geometry) : argument "e2" is missing, with no default Jan 18, 2017 at 11:30
  • Try sF[,-geometry] not sf[,-sf$geometry]
    – ami
    Jan 18, 2017 at 11:34
  • sf[, -geometry] fails with Error in -"geometry" : invalid argument to unary operator. Reproduce with data(meuse, package = "sp"); meuse_sf <- st_as_sf(meuse); meuse_sf[, -geometry] Jan 18, 2017 at 11:38
  • 6
    This does not work in any way. Maybe it did in some earlier sf package, but now it doesn't. All subsetting of sf data frames preserves the geometry column. Please delete.
    – Spacedman
    Jan 5, 2018 at 16:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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