Consider the following:
library(magrittr)
sapply(c("dplyr", "tibble", "tidyr"), requireNamespace)
mytbl <- structure(
list(
A = list(c("A.1", "A.2")),
B = list(c("B.1", "B.2")),
C = list("C.1"),
D = list(c("D.1", "D.2")),
E = list(c("E.1", "E.2", "E.3"))),
class = c("tbl_df", "tbl", "data.frame"),
row.names = c(NA, -1L))
While tidyr::unnest
works for every individual column like so:
lapply(names(mytbl), function(x) tidyr::unnest(mytbl, cols = x))
unnest
ing fails when trying to operate on all columns using tidyselect
:
mytbl %>% tidyr::unnest(cols = dplyr::everything())
Error in `tidyr::unnest()`:
! In row 1, can't recycle input of size 2 to size 3.
Run `rlang::last_trace()` to see where the error occurred.
Any pointers? What is going on here and ho do I prevent this?
The problem arises from the fact that your columns have different lengths (e.g., A is 2, but C is 1, and E is 3). A data.frame
object, which is what returns unnest
, cannot have columns of different lengths.
I'm not aware of an easy solution, but one possibility is to pad NAs to every vector to match the maximum length. This requires pivoting first:
library(dplyr)
library(purrr)
library(tidyr)
mytbl %>%
pivot_longer(everything()) %>%
mutate(value = map(value, `length<-`, max(lengths(value)))) %>%
pivot_wider(names_from = name, values_from = value) %>%
unnest(everything())
output
# A tibble: 3 × 5
A B C D E
<chr> <chr> <chr> <chr> <chr>
1 A.1 B.1 C.1 D.1 E.1
2 A.2 B.2 NA D.2 E.2
3 NA NA NA NA E.3
In base R, you can do:
l <- unlist(mytbl, recursive = FALSE)
as.data.frame(lapply(l, `length<-`, max(lengths(l))))