当我有不同长度的列表列表时,如何获得list_rbind() names_to的好处?

How to get the benefit of list_rbind() names_to when I have have a list of lists of differing lengths?

提问人:Robert Hadow 提问时间:11/6/2023 最后编辑:Robert Hadow 更新时间:11/6/2023 访问量:35

问:

我从JSON下载中获得了两个大对象。在原始形式中,顺序很重要。 长度(物种)与长度(颜色)相同。我很乐意添加另一列或使用行名。从 list_rbind() 来看,rows_to是完美的,但是......

  • list_rbind() 不起作用,因为 colors 不是 dfs 列表。
  • as.data.frame() 不起作用,因为颜色具有不同长度的列表
  • unlist() 丢失信息
    species <- c("roses", "tulips", "lilies")
    colors <- list(list("red"), list("white", "yellow"), list("pink", "white"))

期望的结果

      species colors
    1   roses    red
    2  tulips  white
    3  tulips yellow
    4  lilies   pink
    5  lilies  white

我可以使用 for 循环暴力破解所需的结果,但我有一百万种,每种物种至少有一种颜色,平均有八种颜色。因此,需要一种更智能、更快速的方法。不,真实世界的数据不是字符串。我需要一种更聪明的方法。

取消嵌套不同长度的 DataFrame 列表似乎并不能解决我的挑战。

真实世界

> str(pg, max.level = 2)
'data.frame':   1206169 obs. of  3 variables:
 $ PG : int  1 2 3 4 5 6 7 8 9 10 ...
 $ npi:List of 1206169
  ..$ : int  1376032029 1184159188 1629504501 1598703019 1487200408 1801443619
  ..$ : int 1588809248
  ..$ : int 1497791297
R JSON 嵌套列表

评论


答:

3赞 r2evans 11/6/2023 #1

基础 R

data.frame(
  species = rep(species, times = lengths(colors)),
  colors = unlist(colors)
)
#   species colors
# 1   roses    red
# 2  tulips  white
# 3  tulips yellow
# 4  lilies   pink
# 5  lilies  white

德普莱尔

library(dplyr)
tibble(species, colors) %>%
  unnest(colors) %>%
  mutate(colors = unlist(colors))
# # A tibble: 5 × 2
#   species colors
#   <chr>   <chr> 
# 1 roses   red   
# 2 tulips  white 
# 3 tulips  yellow
# 4 lilies  pink  
# 5 lilies  white 

与真实数据相似:

dat <- data.frame(PG=1:3)
dat$npi <- list(c(1376032029L, 1184159188L, 1629504501L, 1598703019L, 1487200408L, 1801443619L), 1588809248L, 1497791297L)
str(dat)
# 'data.frame': 3 obs. of  2 variables:
#  $ PG : int  1 2 3
#  $ npi:List of 3
#   ..$ : int  1376032029 1184159188 1629504501 1598703019 1487200408 1801443619
#   ..$ : int 1588809248
#   ..$ : int 1497791297

# base R
dat[,-2,drop=FALSE][rep(1:nrow(dat), times = lengths(dat$npi)),,drop=FALSE] |>
  cbind(npi=unlist(dat$npi))
#     PG        npi
# 1    1 1376032029
# 1.1  1 1184159188
# 1.2  1 1629504501
# 1.3  1 1598703019
# 1.4  1 1487200408
# 1.5  1 1801443619
# 2    2 1588809248
# 3    3 1497791297

# dplyr
unnest(dat, npi)
# # A tibble: 8 × 2
#      PG        npi
#   <int>      <int>
# 1     1 1376032029
# 2     1 1184159188
# 3     1 1629504501
# 4     1 1598703019
# 5     1 1487200408
# 6     1 1801443619
# 7     2 1588809248
# 8     3 1497791297

评论

1赞 Robert Hadow 11/6/2023
哇@r2evans!一分钟之内即可解决。它可以在几秒钟内完成 for 循环运行数小时的工作。关键是 lengths()。如果 length() 的手册页(R 文档)提供了 lengths() 也可用的提示,那不是很好吗?
2赞 r2evans 11/6/2023
愿望实现......阅读 ?length 并转到“另请参阅”部分,注意它包括“......用于获取列表中每个元素长度的长度(我过去也曾希望过类似的事情,当这些愿望同样迅速地实现时,我会感到惊讶......显然,阅读“足够”的帮助文档对我来说是一项后天习得和磨练的技能:-)
0赞 r2evans 11/6/2023
..在很长一段时间里,我会跑去得到同样的东西,尽管速度稍微慢一点sapply(somelist, length)