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.


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 '17 at 12:43
  • 1
    is there a piped version of this? sf %>% mutate(geometry = NULL) doesn't work
    – obrl_soil
    Apr 25 '17 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 '17 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 '17 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 '20 at 20:30

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"

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 '20 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 '20 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 '20 at 20:15
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 '17 at 11:30
  • Try sF[,-geometry] not sf[,-sf$geometry]
    – ami
    Jan 18 '17 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 '17 at 11:38
  • 5
    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 '18 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.