Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why does rbind() work and bind_rows() not work in combining these sf objects?

Tags:

r

tidyverse

sf

I've got some sf objects I want to combine. I've stripped them down to a single polygon each (rtmp and rtmp2) for the purposes of this question. rbind() and do.call(rbind,...) seem to work fine, but bind_rows() doesn't. Obviously I can work around this, but what am I missing?

(Data at bottom of question.)

These work:

library(dplyr)  ## version 0.8.3
library(sf)     ## version 0.8.0
r1 <- rbind(rtmp,rtmp2)  ## works
r2 <- do.call(rbind,list(rtmp,rtmp2)) ## works

identical(r1,r2) ## TRUE
all.equal(r1,r2) ## fails??

Error: Can't join on 'geometry' x 'geometry' because of incompatible types (sfc_POLYGON/sfc / sfc_POLYGON/sfc)

This fails:

bind_rows(list(rtmp,rtmp2))

Error in .subset2(x, i) : attempt to select less than one element in get1index
In addition: Warning messages: 1: In bind_rows_(x, .id) : Vectorizing 'sfc_POLYGON' elements may not preserve their attributes 2: In bind_rows_(x, .id) : Vectorizing 'sfc_POLYGON' elements may not preserve their attributes

data

rtmp <- structure(list(PROVCODE = "ON", geometry = structure(list(structure(list(
    structure(c(7201954.77714286, 7206422.6, 7206659.96857143, 
    7206183.55714286, 7206456.25714286, 7206918.87142857, 7207300.78857143, 
    7207337.03428571, 7207488.91714286, 7207400.89428571, 7208110.25714286, 
    7208360.52, 7208664.28571429, 7208710.88571429, 7208819.62285714, 
    7209207.96, 7209308.06285714, 7209665.33428571, 7209425.42857143, 
    7209568.68285714, 7209522.08285714, 7209870.72285714, 7210022.60571429, 
    7210017.42857143, 7210321.19428571, 7210507.59714286, 7210630.14, 
    7210407.49142857, 7210535.21142857, 7210378.15142857, 7210921.82285714, 
    7210906.87428571, 7211255.58285714, 7211310.45142857, 7211675.00857143, 
    7212183.14285714, 7208783.07714286, 7209760.22, 7208297.23714286, 
    7207629.9, 7201954.77714286, 935407.037142857, 937804.568571429, 
    937788.902857143, 937063.325714286, 936599.088571429, 936431.897142857, 
    936498.582857143, 936341.52, 936410.56, 936134.408571429, 
    936103.34, 935840.997142857, 935891.048571429, 935715.002857143, 
    935972.168571429, 936172.38, 935989.428571429, 935885.871428571, 
    935349.102857143, 935278.337142857, 934976.297142857, 934831.317142857, 
    934964.217142857, 934770.911428571, 934691.517142857, 934978.022857143, 
    934460.24, 934237.594285714, 933921.745714286, 933302.131428571, 
    933074.305714286, 932540.708571429, 932384.642857143, 931995.7, 
    932099.337142857, 931815.214285714, 929976.52, 928202.56, 
    927651.188571429, 927094.268571429, 935407.037142857), .Dim = c(41L, 
    2L))), class = c("XY", "POLYGON", "sfg"))), class = c("sfc_POLYGON", 
"sfc"), precision = 0, bbox = structure(c(xmin = 7201954.77714286, 
ymin = 927094.268571429, xmax = 7212183.14285714, ymax = 937804.568571429
), class = "bbox"), crs = structure(list(epsg = NA_integer_, 
    proj4string = NA_character_), class = "crs"), n_empty = 0L)), row.names = c(NA, 
-1L), sf_column = "geometry", agr = structure(c(PROVCODE = NA_integer_), .Label = c("constant", 
"aggregate", "identity"), class = "factor"), class = c("sf", 
"tbl_df", "tbl", "data.frame"))

rtmp2 <- structure(list(PROVCODE = "ON", geometry = structure(list(structure(list(
    structure(c(6914891.13617828, 7022510.44138576, 7130129.74659325, 
    7130129.74659325, 7022510.44138576, 6914891.13617828, 6914891.13617828, 
    896361.565655993, 958495.600487533, 896361.565655993, 772093.495992912, 
    709959.461161371, 772093.495992912, 896361.565655993), .Dim = c(7L, 
    2L), .Dimnames = list(NULL, c("x", "y")))), class = c("XY", 
"POLYGON", "sfg"))), class = c("sfc_POLYGON", "sfc"), precision = 0, bbox = structure(c(xmin = 6914891.13617828, 
ymin = 709959.461161371, xmax = 7130129.74659325, ymax = 958495.600487533
), class = "bbox"), crs = structure(list(epsg = NA_integer_, 
    proj4string = NA_character_), class = "crs"), n_empty = 0L)), row.names = 277L, class = c("sf", 
"data.frame"), sf_column = "geometry", agr = structure(c(PROVCODE = NA_integer_), .Label = c("constant", 
"aggregate", "identity"), class = "factor"))
like image 371
Ben Bolker Avatar asked Oct 31 '19 18:10

Ben Bolker


People also ask

What is the difference between Rbind and bind_rows?

rbind() throws an error whereas bind_rows assigns “NA” to those rows of columns missing in one of the data frames where the value is not provided by the data frames.

What does Rbind function do in R?

Syntax of the rbind() function rbind(): The rbind or the row bind function is used to bind or combine the multiple group of rows together.

Is bind_rows faster than Rbind?

We go back to initializing the output data frame with no rows and then adding the result of each turn of the loop as a new row in the output data frame. But when you now use bind_rows() rather than rbind() it runs much, much faster.

How does bind_rows work in R?

You can use the bind_rows() function from the dplyr package in R to bind together two data frames by their rows: bind_rows(df1, df2, df3, ...) Similarly, you can use the bind_cols() function from dplyr to bind together two data frames by their columns: bind_cols(df1, df2, df3, ...)


1 Answers

I had the same issue before and I figured out that rbindlist does help to combine the list, but you have to convert it back to sf object using st_as_sf()

this works for me:

p <- data.table::rbindlist(list(rtmp,rtmp2),
                           use.names = TRUE,
                           fill = TRUE,
                           idcol = NULL)
st_as_sf(p) 

Simple feature collection with 2 features and 1 field
geometry type:  POLYGON
dimension:      XY
bbox:           xmin: 7201955 ymin: 927094.3 xmax: 7212183 ymax: 937804.6
epsg (SRID):    NA
proj4string:    NA
  PROVCODE                       geometry
1       ON POLYGON ((7201955 935407, 7...
2       ON POLYGON ((6914891 896361.6,...
like image 68
Chuan Avatar answered Oct 02 '22 01:10

Chuan