tidyverse / purrr

A functional programming toolkit for R

Home Page:https://purrr.tidyverse.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

list_rbind() loses spatial class

francisbarton opened this issue · comments

When binding a list of spatial data frames, the sf class is lost from the result.
(Perhaps this is where the ptype argument to list_rbind() is useful, but I don't know what I would need to use there.)

This feels like a loss of functionality, or at least an unexpected result, compared to using dplyr::bind_rows(), or a workflow using map_dfr that I might have used previously.

I'm sure you'll say this is behaving as desired, not a bug, but as a user of purrr this felt like an unexpected behaviour.

nc <- sf::st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE)

test_list <- list(ashe = dplyr::slice(nc, 1), surry = dplyr::slice(nc, 3))

purrr::list_rbind(test_list) |>
  class()
#> [1] "data.frame"

dplyr::bind_rows(test_list) |>
  class()
#> [1] "sf"         "data.frame"

Created on 2023-05-02 with reprex v2.0.2

Seems more odd, since a few years ago when dplyr::bind_rows() started handling binding sf data frames - which was great - this was based on bind_rows() starting to use vctrs::vec_rbind() - which I believe is also the basis for list_rbind()
tidyverse/dplyr#2457 (comment)

From taking a peek at the code, it looks like dplyr::bind_rows() actually overrides vctrs coercion rules and derives the class from the first data frame in:
https://github.com/tidyverse/dplyr/blob/1832ffbbdf3a85145b1545b84ee7b55a99fbae98/R/bind-rows.R#L77-L84

  # Override vctrs coercion rules and instead derive class from first input
  if (is.data.frame(first)) {
    out <- dplyr_reconstruct(out, first)
  } else {
    out <- as_tibble(out)
  }
  out
}

Tracking in related vctrs issue.

Maybe this one r-lib/vctrs#1741