You can use list
in Map
with do.call
.
z <- setNames(do.call(Map, c(list, x[-1])), x[[1]])
identical(z, y)
#[1] TRUE
The same but using pipes:
z <- c(list, x[-1]) |>
do.call(what=Map) |>
setNames(x[[1]])
Benchmark
x <- list(id = c("a", "b"), value = c(1,2), othervalue = c(3,4) )
bench::mark(purr = purrr::transpose(x[-1], .names = x[[1]]), #@Maël
lapplySplit = lapply(split(as.data.frame(x)[-1], x$id), c), #@Allan Cameron
Map = setNames(do.call(Map, c(list, x[-1])), x[[1]]) ) #@GKi
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc
# <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl>
#1 purr 2.51ms 2.64ms 372. 3.69MB 34.2 152 14
#2 lapplySplit 461.77µs 490.48µs 2018. 102.21KB 52.0 892 23
#3 Map 14.13µs 15.9µs 61557. 3.06KB 80.1 9987 13
Map is in this case about 30 times faster and allocates mutch less memory compared to lapplySplit the second.
And with the dataset from @s_baldur:
x <- list(id = c(letters, LETTERS), value = 1:52, othervalue = (1:52 + 100))
bench::mark(check=FALSE,
purr = purrr::transpose(x[-1], .names = x[[1]]), #@Maël
lapplySplit = lapply(split(as.data.frame(x)[-1], x$id), c), #@Allan Cameron
Map = setNames(do.call(Map, c(list, x[-1])), x[[1]]) ) #@GKi
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc
# <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl>
#1 purr 2.5ms 2.59ms 385. 3.69MB 33.9 159 14
#2 lapplySplit 2.43ms 2.51ms 391. 137.21KB 68.3 149 26
#3 Map 50.98µs 61.06µs 15717. 3.51KB 72.5 6506 30
For the updated question use maybe:
lapply(split(setNames(x$value, x$key), x$id), as.list)
But is there a need for a list
? If not then use maybe:
split(setNames(x$value, x$key), x$id)