1

bind_rows can append dataframes even when they do not have identical columns. It fills any non-matching columns with NAs.

Is there an equivalent for spatial point data frames in R?

I have two spdfs I want to combine (row wise) but they have almost no matching columns. I have had a look at the sf package but it doesn't have a method for this (yet?).

UPDATE:

I get an error message trying to replicate suggested solution

data(meuse)
coordinates(meuse) <- ~x+y
meuse <- st_as_sf(meuse)

m1 <- select(meuse, cadmium) 
m2 <- select(meuse, copper)

m3 <- bind_rows(m1, m2)
m3$geometry <- c(m1$geometry, m2$geometry)
m3 <- st_as_sf(m3)

> head(m3)
Error in .subset2(x, i, exact = exact) : 
 attempt to select less than one element in get1index

UPDATE 2:

Don't be an idiot like me and forget the crucial data.frames() step when using bind_rows

4

Since (I think) NA in geometry is not supported, you can bind_rows the data frames and then add on the geometry and convert.

nc1 and nc2 are two sf objects with differing columns:

> nc1
Simple feature collection with 100 features and 2 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: -84.32385 ymin: 33.88199 xmax: -75.45698 ymax: 36.58965
epsg (SRID):    4267
proj4string:    +proj=longlat +datum=NAD27 +no_defs
First 20 features:
   NWBIR74 BIR79                       geometry
1       10  1364 MULTIPOLYGON(((-81.47275543...
2       10   542 MULTIPOLYGON(((-81.23989105...
3      208  3616 MULTIPOLYGON(((-80.45634460...
4      123   830 MULTIPOLYGON(((-76.00897216...
5     1066  1606 MULTIPOLYGON(((-77.21766662...
6      954  1838 MULTIPOLYGON(((-76.74506378...

> nc2
Simple feature collection with 100 features and 2 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: -84.32385 ymin: 33.88199 xmax: -75.45698 ymax: 36.58965
epsg (SRID):    4267
proj4string:    +proj=longlat +datum=NAD27 +no_defs
First 20 features:
   SID79 NWBIR79                       geometry
1      0      19 MULTIPOLYGON(((-81.47275543...
2      3      12 MULTIPOLYGON(((-81.23989105...
3      6     260 MULTIPOLYGON(((-80.45634460...
4      2     145 MULTIPOLYGON(((-76.00897216...
5      3    1197 MULTIPOLYGON(((-77.21766662...

Then I can do this:

vv = bind_rows(data.frame(nc1),data.frame(nc2))
vv$geometry=c(nc1$geometry, nc2$geometry)
vv = st_as_sf(vv)

Which has the NA padding - head:

First 20 features:
   NWBIR74 BIR79 SID79 NWBIR79                       geometry
1       10  1364    NA      NA MULTIPOLYGON(((-81.47275543...
2       10   542    NA      NA MULTIPOLYGON(((-81.23989105...
3      208  3616    NA      NA MULTIPOLYGON(((-80.45634460...
4      123   830    NA      NA MULTIPOLYGON(((-76.00897216...
5     1066  1606    NA      NA MULTIPOLYGON(((-77.21766662...

tail:

proj4string:    +proj=longlat +datum=NAD27 +no_defs
    NWBIR74 BIR79 SID79 NWBIR79                       geometry
195      NA    NA     4     487 MULTIPOLYGON(((-77.14895629...
196      NA    NA     5    1023 MULTIPOLYGON(((-78.26149749...
197      NA    NA     3     763 MULTIPOLYGON(((-78.02592468...
198      NA    NA    17    1832 MULTIPOLYGON(((-78.65571594...
199      NA    NA     9    2100 MULTIPOLYGON(((-77.96073150...
200      NA    NA     6     841 MULTIPOLYGON(((-78.65571594...
  • Thanks for the suggestion, I get an error message will update the question above with details – ASeaton Jun 1 '17 at 15:38
  • Nevermind, I'm an idiot. Missed the crucial data.frames in the bind_rows. Thanks for the solution! – ASeaton Jun 1 '17 at 15:46
0

I'm not aware of an sp method, but I think you could work around the problem in sf by creating an index column in both objects, like:

x <- mutate(x, JOINID = 1:nrow(x))
y <- mutate(y, JOINID = (nrow(x)+1):(nrowx() + nrow(y)))
left_join(x, y, by = 'JOINID')

make sure they're both in the same crs etc first, of course.

0

Similar to @Spacedman, I append dataframes and geometries separately, then bind them together into an sf object.

See here for a function that works similarly to bind_rows.

library(sf)
library(dplyr)

bind_rows_sf <- function(...){
  sf_list <- rlang::dots_values(...)[[1]]

  sfg_list_column <- lapply(sf_list, function(sf) sf$geometry[[1]]) %>% st_sfc
  df <- lapply(sf_list, function(sf) st_set_geometry(sf, NULL)) %>% bind_rows

  sf_appended <- st_sf(data.frame(df, geom=sfg_list_column))

  return(sf_appended)
}

sf_1 <- st_sf(data.frame(a=1, geom=st_sfc(st_point(0:1))))
sf_2 <- st_sf(data.frame(a=2, b=4, geom=st_sfc(st_point(1:2))))
sf_3 <- st_sf(data.frame(a=3, b=5, c=6, geom=st_sfc(st_point())))
sf_list <- list(sf_1, sf_2, sf_3)

sf_123 <- sf_list %>% bind_rows_sf
sf_123

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.