向量列表到列表列表

Fel*_*x M 6 collections r list purrr

我有一个这样构建的列表:

x <- list(id = c("a", "b"),
          value = c(1,2),
          othervalue = c(3,4)
    )

Run Code Online (Sandbox Code Playgroud)

我需要将列表转换为如下结构:

y <- list(a = list(value = 1, othervalue = 3),
          b = list(value = 2, othervalue = 4)
    )

Run Code Online (Sandbox Code Playgroud)

你会怎么做?


编辑:

我偶然发现了这个问题的更高级版本:

这里的输出中有某种嵌套列表。

x <-  list(id = c("a", "b", "a"), key = c("foo", "foo", "bar"), value = c(1, 2, 3))
Run Code Online (Sandbox Code Playgroud)

y <- list(a = list(foo = 1, bar = 2), b  = list(foo = 3))
Run Code Online (Sandbox Code Playgroud)

根据目前的答案,结果是:

$a
$a$key
[1] "foo"

$a$value
[1] 1


$b
$b$key
[1] "foo"

$b$value
[1] 2


$a
$a$key
[1] "bar"

$a$value
[1] 3
Run Code Online (Sandbox Code Playgroud)

GKi*_*GKi 7

您可以listMap一起使用do.call

\n
z <- setNames(do.call(Map, c(list, x[-1])), x[[1]])\n\nidentical(z, y)\n#[1] TRUE\n
Run Code Online (Sandbox Code Playgroud)\n

相同但使用管道:

\n
z <- c(list, x[-1]) |>\n       do.call(what=Map) |>\n       setNames(x[[1]])\n
Run Code Online (Sandbox Code Playgroud)\n
\n

基准

\n
x <- list(id = c("a", "b"), value = c(1,2), othervalue = c(3,4) )\n\nbench::mark(purr = purrr::transpose(x[-1], .names = x[[1]]), #@Ma\xc3\xabl\n            lapplySplit = lapply(split(as.data.frame(x)[-1], x$id), c), #@Allan Cameron\n            Map = setNames(do.call(Map, c(list, x[-1])), x[[1]]) ) #@GKi\n\n# expression       min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc\n#  <bch:expr>  <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>\n#1 purr          2.51ms   2.64ms      372.    3.69MB     34.2   152    14\n#2 lapplySplit 461.77\xc2\xb5s 490.48\xc2\xb5s     2018.  102.21KB     52.0   892    23\n#3 Map          14.13\xc2\xb5s   15.9\xc2\xb5s    61557.    3.06KB     80.1  9987    13\n
Run Code Online (Sandbox Code Playgroud)\n

在这种情况下,与第二个 lapplySplit 相比,Map 的速度大约快 30 倍,并且分配的内存要少得多。
\n以及来自 @s_baldur 的数据集:

\n
x <- list(id = c(letters, LETTERS), value = 1:52, othervalue = (1:52 + 100))\nbench::mark(check=FALSE,\npurr = purrr::transpose(x[-1], .names = x[[1]]), #@Ma\xc3\xabl\nlapplySplit = lapply(split(as.data.frame(x)[-1], x$id), c), #@Allan Cameron\nMap = setNames(do.call(Map, c(list, x[-1])), x[[1]]) ) #@GKi\n#  expression       min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc\n#  <bch:expr>  <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>\n#1 purr           2.5ms   2.59ms      385.    3.69MB     33.9   159    14\n#2 lapplySplit   2.43ms   2.51ms      391.  137.21KB     68.3   149    26\n#3 Map          50.98\xc2\xb5s  61.06\xc2\xb5s    15717.    3.51KB     72.5  6506    30\n
Run Code Online (Sandbox Code Playgroud)\n
\n

对于更新的问题,可能使用:

\n
lapply(split(setNames(x$value, x$key), x$id), as.list)\n
Run Code Online (Sandbox Code Playgroud)\n

但有必要吗list?如果没有,那么可以使用:

\n
split(setNames(x$value, x$key), x$id)\n
Run Code Online (Sandbox Code Playgroud)\n


All*_*ron 4

你可以做

lapply(split(as.data.frame(x)[-1], x$id), c)
#> $a
#> $a$value
#> [1] 1
#> 
#> $a$othervalue
#> [1] 3
#> 
#> 
#> $b
#> $b$value
#> [1] 2
#> 
#> $b$othervalue
#> [1] 4

Run Code Online (Sandbox Code Playgroud)

与以下内容相同y

identical(lapply(split(as.data.frame(x)[-1], x$id), c), y)
#> [1] TRUE
Run Code Online (Sandbox Code Playgroud)