我使用以下格式获得了大list
:
example <- list("12908430751", "12908453145", c("12908453145","12908472085","453145472085"), c("12908453145", "12908472085", "453145472085"), "12908453145", c("12908453145", "12908472085", "453145472085"))
example
[[1]]
[1] "12908430751"
[[2]]
[1] "12908453145"
[[3]]
[1] "12908453145" "12908472085" "453145472085"
[[4]]
[1] "12908453145" "12908472085" "453145472085"
[[5]]
[1] "12908453145"
[[6]]
[1] "12908453145" "12908472085" "453145472085"
虽然使用library(reshape2); melt(example)
适用于较小的数据集,但实际数据(约600万个元素)需要很长时间。我想知道是否有更有效的方法来实现这一点。
Output
value L1
1 12908430751 1
2 12908453145 2
3 12908453145 3
4 12908472085 3
5 453145472085 3
6 12908453145 4
7 12908472085 4
8 453145472085 4
9 12908453145 5
10 12908453145 6
11 12908472085 6
12 453145472085 6
我发现类似的Melt data.frame containing list to long format (efficiently),但未能适应我的情况。
RESULT
谢谢大家,我只是快速检查了我的列表example1
,其中有100万个元素
system.time({foo <- unlist(lapply(example1, function(x) length(x)))
result <- data.frame(value = unlist(example1),
L1 = unlist(sapply(1:length(foo), function(x) rep(x, foo[x]))))})
用户系统已用完 9.63 0.10 9.73
system.time({
df <- structure(list(value = example1 , id = 1:length(example1)), .Names =
c("value", "L1"), row.names = 1:length(example), class = "data.frame")
result1 <- setDT(df)[, .(value = unlist(value)), by = .(L1)]})
用户系统已用完 1.25 0.00 1.26
system.time({result3 <- tibble(L1 = 1:length(example1), value = example1) %>% unnest()})
用户系统已用完 5.99 0.00 5.98
system.time({ stack(setNames(example1, seq_along(example)))})
用户系统已用完 1.08 0.00 1.08
无法让并行版本以结果结束,但可能就在我身边。虽然我没有定义效率,但我采用最快的方法。
答案 0 :(得分:2)
如果你四处寻找可能有更快的方法,但是基础R有stack
可以很快地运行:
stack(setNames(example, seq_along(example)))
# values ind
#1 12908430751 1
#2 12908453145 2
#3 12908453145 3
#4 12908472085 3
#5 453145472085 3
#6 12908453145 4
#7 12908472085 4
#8 453145472085 4
#9 12908453145 5
#10 12908453145 6
#11 12908472085 6
#12 453145472085 6
它的内部基本上是unlist
,然后重复names(x)
的每个值,相应的lengths(x)
次。请参阅utils:::stack.default
以阅读代码。
答案 1 :(得分:0)
您可以在不费力的情况下使用parallel
看到改进
library(parallel)
library(dplyr)
library(reshape2)
library(data.table) # for rleid
cl <- makeCluster(detectCores()) # automatically detect number of cores
clusterEvalQ(cl, { library(reshape2) }) # need to export package to workers
# Split your data into chunks
nchunks <- 2 # does not need to equal number of cores (can be > # of cores but should be close to number of cores)
chunks <- split(example, cut(seq_along(example), nchunks))
result <- parLapply(cl, chunks, function(i) { melt(i) })
stopCluster(cl)
# combine back into data.frame
df <- Reduce("rbind", result)
answer <- df %>%
mutate(L1 = rleid(L1))
输出
value L1
1 12908430751 1
2 12908453145 2
3 12908453145 3
4 12908472085 3
5 453145472085 3
6 12908453145 4
7 12908472085 4
8 453145472085 4
9 12908453145 5
10 12908453145 6
11 12908472085 6
12 453145472085 6
答案 2 :(得分:0)
如果您愿意使用tidyverse
方法,那么如何制作一个tibble
然后unnest
(我不确定这对您的用例有多高效) ):
library(tidyverse)
tibble(L1 = 1:length(example), value = example) %>% unnest()
#> # A tibble: 12 x 2
#> L1 value
#> <int> <chr>
#> 1 1 12908430751
#> 2 2 12908453145
#> 3 3 12908453145
#> 4 3 12908472085
#> 5 3 453145472085
#> 6 4 12908453145
#> 7 4 12908472085
#> 8 4 453145472085
#> 9 5 12908453145
#> 10 6 12908453145
#> 11 6 12908472085
#> 12 6 453145472085
答案 3 :(得分:0)
你可能想试试这个:
df <- structure(list(value = example , id = 1:length(example)), .Names = c("value", "L1"),
row.names = 1:length(example), class = "data.frame")
library(data.table)
setDT(df)[, .(value = unlist(value)), by = .(L1)]
## L1 value
## 1: 1 12908430751
## 2: 2 12908453145
## 3: 3 12908453145
## 4: 3 12908472085
## 5: 3 453145472085
## 6: 4 12908453145
## 7: 4 12908472085
## 8: 4 453145472085
## 9: 5 12908453145
## 10: 6 12908453145
## 11: 6 12908472085
## 12: 6 453145472085