我(再一次)被扁平化嵌套列表困住了。
我有一些列表列(源自 JSON 格式)。
library(tidyr)
library(dplyr)
df = tibble(id = c(1, 2, 3),
branch = list(NULL, list(colA = 'abc', colB = 'mno'),
list(list(colA = 'def', colB = 'uvw'),
list(colA = 'ghi', colB = 'xyz'))))
我想 unnest_wider 列“分支”。这适用于第 1 行和第 2 行:
df %>%
slice(1:2) %>%
unnest_wider(branch)
但是,第 3 行包含一个列表列表,我必须先取消 nest_longer:
bind_rows(
df %>% slice(1,2),
df %>% slice(3) %>% unnest_longer(branch)) %>%
unnest_wider(branch)
上面的代码给出了所需的输出,但我正在寻找一个通用的解决方案,例如:
如果'branch'列的一个元素是'unnamed list'类型(表示有一个lists of lists)那么unnest_longer。然后将 unnest_wider 应用于整个“分支”列
感谢任何帮助!
最佳答案
首先将叶子转换为数据框,然后取消嵌套。
library(dplyr)
library(tidyr)
leaf2df <- function(x) {
if (length(names(x))) as.data.frame(x)
else if (is.list(x)) lapply(x, leaf2df)
}
df %>%
rowwise %>%
mutate(branch = list(bind_rows(leaf2df(branch)))) %>%
ungroup %>%
unnest(branch, keep_empty = TRUE)
给予:
# A tibble: 4 × 3
id colA colB
<dbl> <chr> <chr>
1 1 <NA> <NA>
2 2 abc mno
3 3 def uvw
4 3 ghi xyz
因为 leaf2df 是递归的,只要任何行中的所有叶子都具有相同的父节点,它就应该继续工作。例如,下面我们将最后一行的列表加深了一层,它仍然有效。
df <- tibble(id = c(1, 2, 3),
branch = list(NULL, list(colA = 'abc', colB = 'mno'),
list(list(list(colA = 'def', colB = 'uvw'),
(list(colA = 'ghi', colB = 'xyz'))))))
关于r - 混合 unnest_longer 和 unnest_wider,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73663318/