首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >unnest_longer与unnest_wider的混合

unnest_longer与unnest_wider的混合
EN

Stack Overflow用户
提问于 2022-09-09 14:00:30
回答 4查看 77关注 0票数 3

我(再一次)被扁平的嵌套列表困住了。

我有一些列表列(源自JSON格式)的tibble。

代码语言:javascript
复制
    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行:

代码语言:javascript
复制
df %>% 
  slice(1:2) %>% 
  unnest_wider(branch)

但是,第3行包含了一个列表,我必须首先对这些列表进行unnest_longer:

代码语言:javascript
复制
bind_rows(
  df %>% slice(1,2),
  df %>% slice(3) %>% unnest_longer(branch)) %>% 
  unnest_wider(branch)

上面的代码提供了所需的输出,但我正在寻找一个通用解决方案,如下所示:

如果“分支”列的元素类型为“未命名列表”(指示有列表列表),则unnest_longer。之后,将unnest_wider应用于整个列“分支”

任何帮助都很感激!

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2022-09-09 19:15:04

首先将叶子转换为数据帧,然后取消嵌套。

代码语言:javascript
复制
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)

给予:

代码语言:javascript
复制
# 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是递归的,只要任何行中的所有叶子都有相同的父级,那么它应该继续工作。例如,下面我们已经将最后一行中的列表做得更深了一点,而且它仍然有效。

代码语言:javascript
复制
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'))))))
票数 1
EN

Stack Overflow用户

发布于 2022-09-09 14:20:08

有点复杂,但这里有一个可能的解决方案:

如果df

  • Determine是一个命名的list,则
  1. 将遍历它的行,方法是检查未命名的names(df$branch[[index]])
  2. If -> slice + unnest;如果命名为-> slice
  3. Finally,unnest_wider()

代码语言:javascript
复制
library(tidyr)
library(dplyr)
library(purrr)

map_df(1:nrow(df), function(x) {
  if (is.null(names(df$branch[[x]]))) {
    df %>% slice(x) %>% unnest_longer(branch)
  } else {
    df %>% slice(x)
  }
}) %>% 
  unnest_wider(branch)

返回:

代码语言:javascript
复制
# 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
票数 1
EN

Stack Overflow用户

发布于 2022-09-09 14:42:01

代码语言:javascript
复制
library(tidyverse)
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")
    )
  )
)

unnester <- function(x, grp) {
  if (grp) {
    x <- x |> unnest_longer(branch)
  }
  unnest_wider(x, branch)
}

df |>
  rowwise() |>
  mutate(grp = length(names(unlist(branch))) > 2) |>
  ungroup() |>
  split(~grp) |>
  imap_dfr(~ unnester(.x, .y)) |>
  select(-grp)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73663318

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档