使用tidyr unnest处理NULL值

10

我将一个JSON文件转换为具有嵌套列表结构的data.frame,并希望对其进行解嵌套和展平操作。列表中的一些值是NULL,而unnest不接受这些值。如果我用仅包含NA值的data.frame结构替换NULL值,则会得到所需的结果。

下面是我的问题的简化示例。我尝试用NA data.frame替换NULL值,但由于嵌套结构而没有成功。如何实现所需的结果?

示例

library(tidyr)
input1 <- data.frame(id = c("c", "d", "e"), value = c(7, 8, 9))
input2 <- NULL
input3 <- data.frame(id = c(NA), value = c(NA))

df <- dplyr::tibble(
a = c(1, 2),
b = list(a = input1, c = input2))  
unnest(df)

出现错误:“错误:每列必须是向量列表或数据框列表 [b]”

df2 <- dplyr::tibble(
a = c(1, 2),
b = list(a = input1, c = input3))  
unnest(df2)

得到了期望的输出。


2
已在 tidyr 1.0.0 中修复;请参见 https://github.com/tidyverse/tidyr/issues/436。 - Frank
2个回答

17
我们可以在这里使用purrrmap_lgl。如果您不关心带有NULL的行,则可以使用filterunnest将其简单地删除:
library(tidyverse)

df %>% 
  filter(!map_lgl(b, is.null)) %>% 
  unnest() 
#> # A tibble: 3 x 3
#>       a     id value
#>   <dbl> <fctr> <dbl>
#> 1     1      c     7
#> 2     1      d     8
#> 3     1      e     9

如果您想保留这些行,您可以在展开之后使用 right_join 操作将其还原:

df %>% 
  filter(!map_lgl(b, is.null)) %>% 
  unnest() %>% 
  right_join(select(df, a))
#> Joining, by = "a"
#> # A tibble: 4 x 3
#>       a     id value
#>   <dbl> <fctr> <dbl>
#> 1     1      c     7
#> 2     1      d     8
#> 3     1      e     9
#> 4     2   <NA>    NA

数据

input1 <- data.frame(id = c("c", "d", "e"), value = c(7, 8, 9))
input2 <- NULL
input3 <- data.frame(id = c(NA), value = c(NA))

df <- dplyr::tibble(
  a = c(1, 2),
  b = list(a = input1, c = input2)
)  

2
正如@Frank所指出的那样,在tidyr 1.0.0中,可以使用keep_empty参数来实现这一点。
library(tidyr)

input1 <- data.frame(id = c("c", "d", "e"), value = c(7, 8, 9))
input2 <- NULL

df <- tibble::tibble(
  a = c(1, 2),
  b = list(a = input1, c = input2)
)

unnest(df, cols = b, keep_empty = TRUE)
#> # A tibble: 4 x 3
#>       a id    value
#>   <dbl> <chr> <dbl>
#> 1     1 c         7
#> 2     1 d         8
#> 3     1 e         9
#> 4     2 NA       NA

reprex package (v2.0.1) 于2021年9月24日创建


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接