R 对列表中的特定元素求和

R 对列表中的特定元素求和,r,list,R,List,我使用下面的代码进行计算,但我想知道是否有更方便的方法来解决这个问题。谢谢大家! [[1]] [1] 19 [[2]] [1] 9 [[3]] [1] 2 p不确定是否更方便,但您可以将聚合与您创建的索引一起使用(p): 另一个选项:lappy(split(未列出(a),rep(沿着(b),b)排列),sum)首先,在实际使用向量时,没有理由使用列表。另外两种方法如下: as.list(aggregate(unlist(a), list(rep(1:length(b),b)), sum)[

我使用下面的代码进行计算,但我想知道是否有更方便的方法来解决这个问题。谢谢大家!

[[1]]
[1] 19

[[2]]
[1] 9

[[3]]
[1] 2

p不确定是否更方便,但您可以将聚合与您创建的索引一起使用(p):


另一个选项:
lappy(split(未列出(a),rep(沿着(b),b)排列),sum)

首先,在实际使用向量时,没有理由使用列表。另外两种方法如下:

as.list(aggregate(unlist(a), list(rep(1:length(b),b)), sum)[["x"]])

a我想到了这个问题的一个有趣的解决方案,可能有点奇怪,但我喜欢它:

a <- c(5, 6, 8, 4, 5, 2)
b <- c(3, 2, 1)

f <- function(a, b) c(sum(head(a, b[1])), if(length(b) > 1) f(tail(a, -b[1]), b[-1]))
f(a, b)
# [1] 19  9  2

library(Matrix)
(a %*% bdiag(lapply(b, rep, x = 1)))[1, ]
# [1] 19  9  2
解释
首先,我们取一个完整的累积和。注意:我最初认为
cumsum()
需要一个原子向量(比如),因此我在
cumsum()之前调用了
unlist()
,但感谢@thelatemail指出它也可以处理列表

as.list(diff(c(0,cumsum(a)[cumsum(b)])));
## [[1]]
## [1] 19
##
## [[2]]
## [1] 9
##
## [[3]]
## [1] 2
##
然后通过在
cumsum(b)
上建立索引来提取要求和的范围的端点:

我们可以通过取前导零得到所需的总和:

cumsum(b);
## [1] 3 5 6
cumsum(a)[cumsum(b)];
## [1] 19 28 30
由于您希望将结果作为列表,我们最终需要调用:

演出

lightsnail您的逻辑几乎是我所能想到的全部,尽管它可以缩短为
tapply(unlist(a),rep(seq_-along(b),b),sum)
和另一个
rowsum(unlist(a),rep(b),reorder=FALSE)
@user20650我在考虑您的解决方案时,意识到分组参数需要是
rep(seq_-along(b),b)
而不是
rep(b,b)
,否则
b
中的重复值将错误地聚合到同一组中。我对答案中包含的性能测试应用了修复程序,发现由于某种原因,它实际上提高了解决方案的性能;现在它几乎和我的解决方案一样快:)哦,你说得很对@bgoldst。感谢您的修复/更新。(顺便说一句,回答很好)您可能会丢失
未列出的
-
as.list(diff(c(0,cumsum(a)[cumsum(b)]))
works-tooThanks@thelatemail!我不知道
cumsum()。奇怪的是,
sum()
(和许多其他函数)在列表上不起作用,而
cumsum()
却起作用。谢谢@lightsnail:)很有帮助!谢谢!
as.list(diff(c(0,cumsum(a)[cumsum(b)])));
## [[1]]
## [1] 19
##
## [[2]]
## [1] 9
##
## [[3]]
## [1] 2
##
cumsum(a);
## [1]  5 11 19 23 28 30
cumsum(b);
## [1] 3 5 6
cumsum(a)[cumsum(b)];
## [1] 19 28 30
diff(c(0,cumsum(a)[cumsum(b)]));
## [1] 19  9  2
as.list(diff(c(0,cumsum(a)[cumsum(b)])));
## [[1]]
## [1] 19
##
## [[2]]
## [1] 9
##
## [[3]]
## [1] 2
##
lightsnail <- function() { p<-rep(1:length(b),b); as.list(sapply(1:length(b), function(x) {sum(as.numeric(a)[which(p==x)])})); };
thelatemail <- function() as.list(tapply(unlist(a), rep(seq_along(b), b), sum)); ## added as.list()
psidom <- function() lapply(split(unlist(a), rep(seq_along(b), b)), sum);
tfc <- function() as.list(aggregate(unlist(a), list(rep(1:length(b),b)), sum)[["x"]]);
user20650 <- function() as.list(rowsum(unlist(a), rep(seq_along(b), b), reorder=FALSE));
bgoldst <- function() as.list(diff(c(0,cumsum(a)[cumsum(b)])));

expected <- list(19,9,2);
identical(expected,lightsnail());
## [1] TRUE
identical(expected,unname(thelatemail())); ## ignore names
## [1] TRUE
identical(expected,unname(psidom())); ## ignore names
## [1] TRUE
identical(expected,tfc());
## [1] TRUE
identical(expected,user20650());
## [1] TRUE
identical(expected,bgoldst());
## [1] TRUE

library(microbenchmark);
microbenchmark(lightsnail(),thelatemail(),psidom(),tfc(),user20650(),bgoldst(),times=1e3L);
## Unit: microseconds
##           expr     min      lq      mean  median      uq      max neval
##   lightsnail()  26.088  33.358  37.34079  37.206  39.344  100.927  1000
##  thelatemail() 121.881 135.139 151.77782 142.837 150.963 3547.386  1000
##       psidom()  48.753  55.595  61.13800  59.016  63.507  276.693  1000
##          tfc() 574.767 613.256 646.64302 628.652 645.757 1923.586  1000
##    user20650()  17.534  23.094  25.49522  25.232  26.943  101.782  1000
##      bgoldst()  10.264  14.969  17.61914  17.535  18.817   82.965  1000