rbind 包含不同长度列表的数据框列
rbind a dataframe column containing list of different lengths
我有一个数据框,有一列包含不同长度的列表:
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 万)时,它会永远运行并崩溃。
有没有办法将其有效地应用于更大的数据集?
谢谢!
澄清后更新:
另一种选择是使用 stringi
中的 stri_list2matrix
,速度非常快。
library(stringi)
op <- as.data.frame(stri_list2matrix(c(IP$V1), byrow = TRUE))
op$.id <- seq_along(IP$V1)
基本的 R 解决方案是使用 lapply
,这也非常快(尽管在 benchmark image 中有很多可变性)。
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)
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
因为它比 plyr
或 tidyr
.
更快
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
澄清后更新:
我们可以使用 tidyr_package:
中的 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
None 的解决方案重复了 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)
或手动覆盖它们。我不建议这样做,但这取决于您的需求。
我有一个数据框,有一列包含不同长度的列表:
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 万)时,它会永远运行并崩溃。
有没有办法将其有效地应用于更大的数据集?
谢谢!
澄清后更新:
另一种选择是使用 stringi
中的 stri_list2matrix
,速度非常快。
library(stringi)
op <- as.data.frame(stri_list2matrix(c(IP$V1), byrow = TRUE))
op$.id <- seq_along(IP$V1)
基本的 R 解决方案是使用 lapply
,这也非常快(尽管在 benchmark image 中有很多可变性)。
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)
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
因为它比 plyr
或 tidyr
.
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
澄清后更新: 我们可以使用 tidyr_package:
中的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
None 的解决方案重复了 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)
或手动覆盖它们。我不建议这样做,但这取决于您的需求。