List 挑战:优化未上市[简单]
因为SO最近有点慢,所以我发布了一个简单的问题。如果大鱼们能在这场比赛中坐在板凳上,给新秀一个回应的机会,我将不胜感激 有时,我们的对象有大量的大型列表元素(向量)。如何将此对象“取消列表”到单个向量中。证明您的方法比List 挑战:优化未上市[简单],list,optimization,r,vector,List,Optimization,R,Vector,因为SO最近有点慢,所以我发布了一个简单的问题。如果大鱼们能在这场比赛中坐在板凳上,给新秀一个回应的机会,我将不胜感激 有时,我们的对象有大量的大型列表元素(向量)。如何将此对象“取消列表”到单个向量中。证明您的方法比unlist()更快非unlist()解决方案必须非常快才能击败unlist(),不是吗?在这里,不到两秒钟就可以取消列出每个长度为100000的2000个数字向量的列表 > bigList2 <- as.list(data.frame(matrix(rep(rnorm
unlist()
更快非unlist()
解决方案必须非常快才能击败unlist()
,不是吗?在这里,不到两秒钟就可以取消列出每个长度为100000的2000个数字向量的列表
> bigList2 <- as.list(data.frame(matrix(rep(rnorm(1000000), times = 200),
+ ncol = 2000)))
> print(object.size(bigList2), units = "Gb")
1.5 Gb
> system.time(foo <- unlist(bigList2, use.names = FALSE))
user system elapsed
1.897 0.000 2.019
。。。最后,use.names=TRUE
版本完成了…:
> system.time(foo <- unlist(bigList2, use = TRUE))
user system elapsed
2307.839 10.978 2335.815
>system.time(foo如果你不需要名字,而且你的列表只有一级深,那么如果你能击败
.Internal(unlist(your_list, FALSE, FALSE))
在接下来的一年里,我会投票支持你所做的一切
[更新:如果需要非唯一的名称,并且列表不是递归的,那么这里有一个版本,它比未列出的名称改进了100倍
myunlist <- function(l){
names <- names(l)
vec <- unlist(l, F, F)
reps <- unlist(lapply(l, length), F, F)
names(vec) <- rep(names, reps)
vec
}
myunlist(list(a=1:3, b=2))
a a a b
1 2 3 2
> tl <- list(a = 1:20000, b = 1:5000, c = 2:30)
> system.time(for(i in 1:200) unlist(tl))
user system elapsed
22.97 0.00 23.00
> system.time(for(i in 1:200) myunlist(tl))
user system elapsed
0.2 0.0 0.2
> system.time(for(i in 1:200) unlist(tl, F, F))
user system elapsed
0.02 0.00 0.02
myunlist作为一条中等大小的鱼,我首先尝试了一种解决方案,它为小鱼提供了一个基准。它比unlist慢大约3倍
我使用的是ucfagls
测试列表的较小版本(因为它更适合内存)
bigList3c()
具有逻辑参数recursive
,当设置为TRUE
(默认值显然是FALSE
)时,该参数将递归取消列出向量
l这里的每个人都是一条“大鱼”;)。你正在冒着得不到任何答案的风险。有多大?我们说的是鲑鱼、马林鱼还是鲸鲨?什么是“数量荒谬的大列表元素”的意思?长度1000000或更长的向量?有多少列表元素是“荒谬”的数量?必须保留向量的名称?如果是,则必须是唯一的?列表是递归的?默认的非列表可以实现所有这些。假设有几个10000个列表元素,但我会让想象力尽情发挥。一般来说,元素的数量应该足够大,以显示速度性能的任何差异,但在内存限制内。名称可以转储d、 让我们假设list有+1,这可能不重要,但在我的测试中,您的版本比@ucfagls快一点。然而,最大的加速是从use.names=F中获得的。我从Roman的问题中了解到,他的愿望是替换内置的“unlist”就我而言,这是不可能的,当名字不需要的时候。这是一个不能拒绝的提议!如果我一天写6个项目,我可能会有机会抓住德克。FWWW,我认为大的鱼有1000个点。在我的系统中没有选择。(bigList2,recursive=FALSE,use.names=FALSE)
和.Internal(unlist(bigList2,FALSE,FALSE)
。unlist()中的开销
在调用.Internal
之前,调用可以忽略不计。除非我真的非常确定我有正确的对象,否则我会尽量远离.Internal
,以防万一,因为如果出现错误或提供了函数不期望的内容,您可能会使R崩溃。@ucfagis,这对于大向量和小迭代来说是正确的。但是,如果您的列表只包含小向量,并且您运行了长时间的模拟,则.Internal的改进可能会达到两倍!!!中等大小?据您介绍,在过去30天内,您是第10位回答者,并且一直是第7位;)哇。我还没意识到。耶。无论如何,我的提议仍然有效。改进/击败我的答案->获得升级投票。在我的机器上,你的东西大约慢了5倍。完全重启后,它只慢了3.5倍。我更新了你挑战的答案nr3。等待升级投票:)
myunlist <- function(l){
names <- names(l)
vec <- unlist(l, F, F)
reps <- unlist(lapply(l, length), F, F)
names(vec) <- rep(names, reps)
vec
}
myunlist(list(a=1:3, b=2))
a a a b
1 2 3 2
> tl <- list(a = 1:20000, b = 1:5000, c = 2:30)
> system.time(for(i in 1:200) unlist(tl))
user system elapsed
22.97 0.00 23.00
> system.time(for(i in 1:200) myunlist(tl))
user system elapsed
0.2 0.0 0.2
> system.time(for(i in 1:200) unlist(tl, F, F))
user system elapsed
0.02 0.00 0.02
bigList3 <- replicate(500, rnorm(1e3), simplify = F)
unlist_vit <- function(l){
names(l) <- NULL
do.call(c, l)
}
library(rbenchmark)
benchmark(unlist = unlist(bigList3, FALSE, FALSE),
rjc = unlist_rjc(bigList3),
vit = unlist_vit(bigList3),
order = "elapsed",
replications = 100,
columns = c("test", "relative", "elapsed")
)
test relative elapsed
1 unlist 1.0000 2.06
3 vit 1.4369 2.96
2 rjc 3.5146 7.24
bigList3 <- as.list(data.frame(matrix(rep(rnorm(1e5), times = 200), ncol = 2000)))
unlist_rjc <- function(l)
{
lengths <- vapply(l, length, FUN.VALUE = numeric(1), USE.NAMES = FALSE)
total_len <- sum(lengths)
end_index <- cumsum(lengths)
start_index <- 1 + c(0, end_index)
v <- numeric(total_len)
for(i in seq_along(l))
{
v[start_index[i]:end_index[i]] <- l[[i]]
}
v
}
t1 <- system.time(for(i in 1:10) unlist(bigList2, FALSE, FALSE))
t2 <- system.time(for(i in 1:10) unlist_rjc(bigList2))
t2["user.self"] / t1["user.self"] # 3.08
l <- replicate(500, rnorm(1e3), simplify = F)
microbenchmark::microbenchmark(
unlist = unlist(l, FALSE, FALSE),
c = c(l, recursive = TRUE, use.names = FALSE)
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# unlist 3.083424 3.121067 4.662491 3.172401 3.985668 27.35040 100
# c 3.084890 3.133779 4.090520 3.201246 3.920646 33.22832 100