26

Here is a code snippet:

y <- purrr::map(1:2, ~ c(a=.x))
test1 <- dplyr::bind_rows(y)
test2 <- do.call(dplyr::bind_rows, y)

The first call to bind_rows (test1) generates the error

Error in bind_rows_(x, .id) : Argument 1 must have names

Using do.call to invoke bind_rows (test2), on the other hand, works as expected:

test2
# A tibble: 2 x 1
      a
  <int>
1     1
2     2

Why? This is using dplyr 0.7.6 and purrr 0.2.5. If I use map_df instead of map, it fails with the same error.

Note: It doesn't appear to me that this question is the same as Error in bind_rows_(x, .id) : Argument 1 must have names using map_df in purrr.

EDIT: The other way to address this issue is by explicitly creating a dataframe in the first place:

y <- purrr::map(1:2, ~ data.frame(a=.x))

test1 and test2 are now created with no errors and are identical.

Alternatively,this creates the test2 data frame in one step:

purrr::map_df(1:2, ~ data.frame(a=.x))
Robert McDonald
  • 1,250
  • 1
  • 12
  • 20

2 Answers2

27

From the documentation of bind_rows:

Note that for historical reasons, lists containg vectors are always treated as data frames. Thus their vectors are treated as columns rather than rows, and their inner names are ignored

Here, your y as constructed has only inner names - it is two unnamed list elements, each containing a length-one vector with the vector element named a. So this error seems to be expected.

If you name the list elements, you can see that it behaves as described, with the vectors treated as columns:

library(tidyverse)
y <- map(1:2, ~ c(a=.x)) %>%
  set_names(c("a", "b"))
bind_rows(y)
#> # A tibble: 1 x 2
#>       a     b
#>   <int> <int>
#> 1     1     2

The difference with supplying y as arguments via do.call is that it's more like writing bind_rows(c(a = 1), c(a = 2)). This is not a list containing vectors, but separate vectors, so it binds by row as expected.

Calum You
  • 14,687
  • 4
  • 23
  • 42
  • 1
    Thanks. But what is the definition of "inner name"?? Does that refer to the name attribute of a vector? That term doesn't appear in R-ints, R-lang, or R-intro. – Robert McDonald Sep 25 '18 at 20:56
  • Here it does, I believe. I don't think it is supposed to connote anything other than names of things inside the list elements, as opposed to the names of the elements. But because we're talking about a list of vectors, that means the names of the vectors. – Calum You Sep 25 '18 at 22:13
  • 1
    Your answer also explains why rbind and cbind seemed to work backwards in this context. I didn't mention it but it was pretty confusing. There are lots of twisty edges and dark corners in R :-) – Robert McDonald Sep 25 '18 at 23:26
6

bind_rows() will also output the error Error: Argument 1 must have names. if you attempt to bind rows to a matrix instead of a data frame. Make sure you are not passing it a matrix.

Megatron
  • 15,909
  • 12
  • 89
  • 97