76

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.

eivindhammers
  • 1,143
  • 1
  • 8
  • 13

4 Answers4

84

To drop the geometry column, use st_drop_geometry():

library(sf)
nc <-  st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE)
nc_df2 <- nc %>% st_drop_geometry()
class(nc_df2)
#> [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:

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

nc_df <- nc %>% st_set_geometry(NULL)
class(nc_df)
#> [1] "data.frame"
Josh O'Brien
  • 927
  • 5
  • 15
mfherman
  • 941
  • 6
  • 6
50

Set the st_geometry property to NULL.

library(sf)
nc <-  st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE)
class(nc)
## [1] "sf"         "data.frame"
st_geometry(nc) <- NULL
class(nc)
## [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)
as.data.frame(nc)
mdsumner
  • 8,196
  • 1
  • 27
  • 30
  • I had tried nc$geometry <- NULL before, but your suggestion did the trick. Thank you. – eivindhammers 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 00: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 02: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. – Jeffrey Evans Dec 05 '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 05 '20 at 20:30
  • recommend to use st_set_geometry(sf, NULL) or sfheaders::sf_to_df(sf, keep = TRUE) if you want the coords as well (keep refers to the data though, but same effect ultimately) – mdsumner May 06 '20 at 03:34
  • This retains the geometry column but drops the actual geometry as.data.frame(x) and, since the geometry column is always the last one, you can drop the attribute column using as.data.frame(x)[,-ncol(x)] This would allow for using it in a pipe version of code. – Jeffrey Evans Jul 13 '20 at 16:45
  • @JeffreyEvans: The geometry column is not always the last one. Case in point: read_sf(system.file("shape/nc.shp", package = "sf")) %>% mutate(lastcol = 1). – eivindhammers Jul 17 '20 at 23:05
1

why not simply select the columns that you would like?

as.data.frame(sf[,"some column name"])[,1]
joaoal
  • 891
  • 7
  • 14
  • This extracts a single column as a vector (sf$\some column name`` is equivalent and simpler), and does not answer the question. – eivindhammers 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
  • 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".

  • 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.

  • – eivindhammers Jul 22 '20 at 20:15