rbind一个包含不同长度列表的数据框列

3

我有一个数据框,其中一列包含长度不同的列表:

IP <- structure(list(V1 = list(l1 = c("M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M"), `l2` = c("D", 
"D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", 
"D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M"), `l3` = c("D", 
"D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", 
"D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", 
"D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", 
"D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", 
"D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", 
"D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", 
"D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "D", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", 
"M"))), class = "data.frame", row.names = c("1", "2", "3"))

我正在使用以下命令来转换列表。对于较小的数据集,这个命令可以正常工作。
output <- plyr::ldply(IP$V1, rbind)

但是,当我将这个应用到一个大数据集(大约>100万)时,它会运行很长时间并崩溃。

有没有一种更有效的方法来处理更大的数据集?

谢谢!

3个回答

3

没有任何一种解决方案能够复制 plyr::ldply 的输出结果。具体而言,

out1 <- plyr::ldply(IP$V1, rbind)
out1[,c(1:3, 378:380)]
#   .id 1 2  377  378  379
# 1  l1 M M    M    M    M
# 2  l2 D D <NA> <NA> <NA>
# 3  l3 D D    M    M    M

这个问题的复杂性在于嵌套列表的长度不相同:

lengths(IP$V1)
#  l1  l2  l3 
# 379 370 379 

建议的第一个解决方案在修正这种差异后,将会更加有效(无警告)。
IP$V1 <- lapply(IP$V1, `length<-`, max(lengths(IP$V1)))
out2 <- data.frame(do.call(rbind, IP$V1))
out2$.id <- seq_along(IP$V1)
dim(out2)
# [1]   3 380
out2[,c(1:3, 378:380)]
#    V1 V2 V3 V378 V379 .id
# l1  M  M  M    M    M   1
# l2  D  D  D <NA> <NA>   2
# l3  D  D  D    M    M   3

如果您真的希望列名只是数字(字符串形式),您可以使用 out2 <- data.frame(..., check.names = FALSE),或手动覆盖它们。我不建议这样做,但这取决于您的需求。

如果你真的想让列名仅仅是数字(作为字符串),你可以使用 out2 < - data.frame(...,check.names = FALSE) 或者手动覆盖它们。我不推荐这样做,但这取决于你的需求。


2

澄清后更新: 我们可以使用tidyr包中的unnest_wider函数:

library(dplyr)
library(tidyr)

IP %>% 
  unnest_wider(V1, names_sep = "_")

  V1_1  V1_2  V1_3  V1_4  V1_5  V1_6  V1_7  V1_8  V1_9  V1_10 V1_11 V1_12
  <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 M     M     M     M     M     M     M     M     M     M     M     M    
2 D     D     D     D     D     D     D     D     D     D     D     D    
3 D     D     D     D     D     D     D     D     D     D     D     D    
# ... with 367 more variables: V1_13 <chr>, V1_14 <chr>, V1_15 <chr>,
#   V1_16 <chr>, V1_17 <chr>, V1_18 <chr>, V1_19 <chr>, V1_20 <chr>,
#   V1_21 <chr>, V1_22 <chr>, V1_23 <chr>, V1_24 <chr>, V1_25 <chr>,
#   V1_26 <chr>, V1_27 <chr>, V1_28 <chr>, V1_29 <chr>, V1_30 <chr>,
#   V1_31 <chr>, V1_32 <chr>, V1_33 <chr>, V1_34 <chr>, V1_35 <chr>,
#   V1_36 <chr>, V1_37 <chr>, V1_38 <chr>, V1_39 <chr>, V1_40 <chr>,
#   V1_41 <chr>, V1_42 <chr>, V1_43 <chr>, V1_44 <chr>, V1_45 <chr>, ...

第一个答案: 我们可以先转换为data.table,然后使用data.table代码:

library(data.table)
dt1 <- as.data.table(IP)
dt1[, .(V1 = unlist(V1)), by = setdiff(names(dt1), 'V1')]

 V1
   1:  M
   2:  M
   3:  M
   4:  M
   5:  M
  ---   
1124:  M
1125:  M
1126:  M
1127:  M
1128:  M

1

澄清后更新: 另一个选项是使用来自stringistri_list2matrix,非常快速。

library(stringi)

op <- as.data.frame(stri_list2matrix(c(IP$V1), byrow = TRUE))
op$.id <- seq_along(IP$V1)

一个基本的R解决方案是使用lapply,这也非常快(尽管有很多变异性,如基准测试图像所示)。

op3 <-
  as.data.frame(transpose(setDT(lapply(
    c(IP$V1), "length<-", max(lengths(c(ok$V1)))
  ))))
op3$.id <- seq_along(IP$V1)

另一个基于R语言的解决方案是使用sapply,它也相当快速(虽然比lapply略慢)。

op2 <- as.data.frame(t(sapply(c(IP$V1), "length<-", max(lengths(c(IP$V1))))))
op2$.id <- seq_along(IP$V1)

输出

# A tibble: 3 × 380
  V1    V2    V3    V4    V5    V6    V7    V8    V9    V10   V11   V12   V13   V14   V15   V16   V17   V18   V19  
  <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 M     M     M     M     M     M     M     M     M     M     M     M     M     M     M     M     M     M     M    
2 D     D     D     D     D     D     D     D     D     D     D     D     D     D     D     D     D     D     D    
3 D     D     D     D     D     D     D     D     D     D     D     D     D     D     D     D     D     D     D    
# … with 361 more variables: V20 <chr>, V21 <chr>, V22 <chr>, V23 <chr>, V24 <chr>, V25 <chr>, V26 <chr>, V27 <chr>,
#   V28 <chr>, V29 <chr>, V30 <chr>, V31 <chr>, V32 <chr>, V33 <chr>, V34 <chr>, V35 <chr>, V36 <chr>, V37 <chr>,
#   V38 <chr>, V39 <chr>, V40 <chr>, V41 <chr>, V42 <chr>, V43 <chr>, V44 <chr>, V45 <chr>, V46 <chr>, V47 <chr>,
#   V48 <chr>, V49 <chr>, V50 <chr>, V51 <chr>, V52 <chr>, V53 <chr>, V54 <chr>, V55 <chr>, V56 <chr>, V57 <chr>,
#   V58 <chr>, V59 <chr>, V60 <chr>, V61 <chr>, V62 <chr>, V63 <chr>, V64 <chr>, V65 <chr>, V66 <chr>, V67 <chr>,
#   V68 <chr>, V69 <chr>, V70 <chr>, V71 <chr>, V72 <chr>, V73 <chr>, V74 <chr>, V75 <chr>, V76 <chr>, V77 <chr>,
#   V78 <chr>, V79 <chr>, V80 <chr>, V81 <chr>, V82 <chr>, V83 <chr>, V84 <chr>, V85 <chr>, V86 <chr>, V87 <chr>, …

基准测试

library (tidyverse)

bm <- microbenchmark::microbenchmark(
  r2evans = {IP$V1 <- lapply(IP$V1, `length<-`, max(lengths(IP$V1)));
  out2 <- data.frame(do.call(rbind, IP$V1));
  out2$.id <- seq_along(IP$V1)},
  RduU = {plyr::ldply(IP$V1, rbind)},
  tidyr = {IP %>%
    unnest_wider(V1, names_sep = "_")},
  stringi = {op <- as.data.frame(stri_list2matrix(c(IP$V1), byrow=TRUE)); op$.id <- seq_along(IP$V1)},
  sapply = {as.data.frame(t(sapply(c(IP$V1), "length<-", max(lengths(c(IP$V1)))))); op2$.id <- seq_along(IP$V1)},
  lapply = {op3 <- as.data.frame(transpose(setDT(lapply(c(IP$V1), "length<-", max(lengths(c(ok$V1)))))));
  op3$.id <- seq_along(IP$V1)},
  times = 100
)

microbenchmark:::autoplot(bm)

enter image description here

Unit: microseconds
    expr       min         lq        mean     median         uq       max neval
 r2evans  1503.602  1640.0915  1799.95612  1747.6035  1872.3480  3092.314   100
    RduU  1764.108  2003.0560  2150.63791  2086.5735  2232.9945  4152.803   100
   tidyr 15108.671 15938.5185 17209.04116 16487.6840 17480.8740 33108.209   100
 stringi   747.871   819.4205   875.45533   853.2315   913.2410  1569.510   100
  sapply  1056.223  1173.0940  1294.82064  1255.7130  1337.3275  2450.791   100
  lapply   939.044  1078.7225  1335.96819  1139.3605  1236.4150 13476.396   100

第一个答案:您可以使用data.table,它比plyrtidyr更快。

library(data.table)

setDT(IP)[, list(V1 = as.character(unlist(V1)))] %>% 
  as.data.frame()

基准测试

library (dplyr)

microbenchmark::microbenchmark(
  data.table = setDT(IP)[, list(V1 = as.character(unlist(V1)))] %>%
    as.data.frame(),
  tidyr = tidyr::unnest(IP, cols = c(V1)),
  plyr = plyr::ldply(IP$V1, rbind)
)


Unit: microseconds
       expr      min        lq       mean   median        uq       max neval
 data.table  588.723  679.6965  768.05463  745.360  808.5615  1465.043   100
      tidyr 2631.968 2833.8095 3269.19794 3054.737 3393.4345 12726.122   100
       plyr 1173.735 1290.8645 1379.57338 1335.448 1412.0445  2027.333   100

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