我有一个数据框,其中包含列表。
df <- data.frame(
id=c(1:4),
a=I(list(c(1,"a1"),2,c("a31","a32","a33"),"a4")),
b=I(list(2,c("b1","b2",3),c("b3","b4"),4))
); print(df)
id a b
1 1 1, a1 2
2 2 2 b1, b2, 3
3 3 a31, a32.... b3, b4
4 4 a4 4
现在,我需要
unnest
列表来获取这样的数据框:
df2 <- data.frame(
id=c(1,1,2,2,2,3,3,3,3,3,3,4),
a=c(1,"a1",2,2,2,"a31","a31","a32","a32","a33","a33","a4"),
b=c(2,2,"b1","b2",3,"b3","b3","b3","b4","b4","b4",4)
) ; print(df2)
id a b
1 1 1 2
2 1 a1 2
3 2 2 b1
4 2 2 b2
5 2 2 3
6 3 a31 b3
7 3 a31 b3
8 3 a32 b3
9 3 a32 b4
10 3 a33 b4
11 3 a33 b4
12 4 a4 4
我曾经使用
unnest()
来表示那些在某些行/列中包含相同数量的列表元素,但当前数据框在某些行和列中包含不同数量的元素。目前我面临以下错误。
> target <- c("id","a","b")
> df %>% unnest(cols=target)
Error in `unnest()`:
! In row 3, can't recycle input of size 3 to size 2.
Run `rlang::last_trace()` to see where the error occurred.
由于发生的位置(行/列)和它将包含多少元素的不可预测性,我找不到适当的方法来解决这个问题。
我很欣赏你的建议,特别是简单的建议,可以集成到
dplyr
中当前的管道操作中。 Base R
也欢迎其他方式。
您可以尝试使用
expand.grid
和 Map
,如下所示
with(
df,
setNames(
do.call(
rbind,
Map(expand.grid, id, a, b, stringsAsFactors = FALSE)
),
names(df))
)
这给出了
id a b
1 1 1 2
2 1 a1 2
3 2 2 b1
4 2 2 b2
5 2 2 3
6 3 a31 b3
7 3 a32 b3
8 3 a33 b3
9 3 a31 b4
10 3 a32 b4
11 3 a33 b4
12 4 a4 4