在 R 中,我知道如何将(命名)列表列的元素提取到单独的列中,前提是它们的长度相同:
library(tidyverse)
tib1 <- tibble(x = 1:3, y = list(list(a = 1, b = 2, c = 3),
list(a = 3, b = 4, c = 5),
list(a = 5, b = 6, c = 7)))
tib1
# A tibble: 3 x 2 x y <int> <list> 1 1 <list [3]> 2 2 <list [3]> 3 3 <list [3]>
bind_cols(tib1[1], bind_rows(tib1$y))
# A tibble: 3 x 4 x a b c <int> <dbl> <dbl> <dbl> 1 1 1.00 2.00 3.00 2 2 3.00 4.00 5.00 3 3 5.00 6.00 7.00
问题是一旦列表中的一个元素的长度不同(这里是a
):
tib2 <- tibble(x = 1:3, y = list(list(a = 1:2, b = 2, c = 3),
list(a = 3:4, b = 4, c = 5),
list(a = 5:6, b = 6, c = 7)))
bind_cols(tib2[1], bind_rows(tib2$y))
Error in bind_rows_(x, .id) : Argument 2 must be length 2, not 1
有没有一种优雅的方式告诉 R 在提取中不包含 a
,或者只包含 b
和 c
,或者只包含 b
和 c
包含长度相同的元素l
?希望以“pipe-ish”、“tidyverse-ish”的方式?
预期结果应该以某种方式保留a
,或者简单地保留整个y
字段,以便我将来可以以某种方式访问它:
tibble(x = 1:3, y = list(list(a = 1:2, b = 2, c = 3),
list(a = 3:4, b = 4, c = 5),
list(a = 5:6, b = 6, c = 7)),
b = c(2, 4, 6),
c = c(3, 5, 7))
# A tibble: 3 x 4 x y b c <int> <list> <dbl> <dbl> 1 1 <list [3]> 2.00 3.00 2 2 <list [3]> 4.00 5.00 3 3 <list [3]> 6.00 7.00
或者最好作为新的列表列:
tibble(x = 1:3,
a = list(1:2, 3:4, 5:6),
b = c(2, 4, 6),
c = c(3, 5, 7))
# A tibble: 3 x 4 x a b c <int> <list> <dbl> <dbl> 1 1 <int [2]> 2.00 3.00 2 2 <int [2]> 4.00 5.00 3 3 <int [2]> 6.00 7.00
最佳答案
这也是一个基本的 R 解决方案,
dd <- data.frame(x = tib2$x, t(do.call(cbind, tib2$y)))
这给出了,
x a b c 1 1 1, 2 2 3 2 2 3, 4 4 5 3 3 5, 6 6 7
检查结构,我们看到所有三列都是列表。
str(dd)
'data.frame': 3 obs. of 4 variables:
$ x: int 1 2 3
$ a:List of 3
..$ : int 1 2
..$ : int 3 4
..$ : int 5 6
$ b:List of 3
..$ : num 2
..$ : num 4
..$ : num 6
$ c:List of 3
..$ : num 3
..$ : num 5
..$ : num 7
如果您想取消列出 b
和 c
,那么只需:
dd[-c(1, 2)] <- lapply(dd[-c(1, 2)], unlist)
给出了结构:
str(dd)
'data.frame': 3 obs. of 4 variables:
$ x: int 1 2 3
$ a:List of 3
..$ : int 1 2
..$ : int 3 4
..$ : int 5 6
$ b: num 2 4 6
$ c: num 3 5 7
关于r - 将列表列的*特定*元素提取到新列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49094974/