R - 向量化 a which 操作

3

你好,我有一个在R中需要优化性能的函数。我需要向量化for循环。我的问题在于略微复杂的数据结构以及使用“which”命令执行查找的方式。

假设我们正在处理5个元素(1,2,3,4,5),10x2矩阵对是所有唯一对5个元素的组合(即(1,2),(1,3),(1,4)....(4,5))。all_prods是一个10x1的矩阵,我需要在迭代所有5个元素时使用这些对进行查找。

因此,对于1,我需要从all_prods中索引第1、2、3、4行(即对1,2 1,3 1,4和1,5)等等,对于1、2、3、4、5都是如此。

我最近才从matlab转到R,所以非常希望得到任何帮助。

foo <- function(AA , BB , CC ){
    pa <- AA*CC;
    pairs <-  t(combn(seq_len(length(AA)),2));

    all_prods <- pa[pairs[,1]] * pa[pairs[,2]];

    result <- matrix(0,1,length(AA));

    # WANT TO VECTORIZE THIS BLOCK
    for(st in seq(from=1,to=length(AA))){
       result[st] <- sum(all_prods[c(which(pairs[,1]==st), which(pairs[,2]==st))])*BB[st];
    }
   return(result);
}
AA <- seq(from=1,to=5); BB<-seq(from=11,to=15); CC<-seq(from=21,to=25);
results <- foo(AA,BB,CC);

#final results is [7715 164208 256542 348096 431250]

我希望将for循环转换为向量化版本。不需要遍历每个元素st,我想用一个命令完成它并给我一个结果向量(而不是逐个构建它)。

1
我建议您提供一些样本数据以供测试。请参阅https://dev59.com/eG025IYBdhLWcg3whGSx - Roman Luštrik
我尝试了一个sapply的解决方案,但与您实现的结果相当(表扬您预先分配对象)。经过分析,似乎大部分时间都花在了which上。Rprof("vekt.txt"); results <- foo(AA,BB,CC); Rprof(); summaryRprof("vekt.txt") - Roman Luštrik
再次感谢Roman。这就是为什么我想要向量化它或以其他方式重写它的原因(我的理解是apply家族是编写循环的一种优雅方式,但不是性能提升)。另外再次感谢你介绍给我RProf :) - user1480926
这个回答解决了你的问题吗?在矩阵的行上向量化哪个操作 - EJoshuaS - Stand with Ukraine
给潜在的关闭投票审查者:请注意,此帖子作为 [which] 标签清除的一部分进入队列。我不同意所提出的重复标记是合理的。至少需要第二个重复标记。我已经投票保持开放状态。 - Ian Campbell
显示剩余2条评论
1个回答

8
您可以像这样编写您的函数:

foo <- function(AA, BB, CC) {
  pa <- AA*CC
  x <- outer(pa, pa)
  diag(x) <- 0
  res <- colSums(x)*BB
  return(res)
}

关键是不要打破对称性。使用有序的“对”对应于我的矩阵 x 的右上三角形。虽然这似乎只需要计算一半的值,但语法和计算开销变得相当大。你区分了 st 是对中的第一个元素和第二个元素的情况。后来在消除这种区别时会遇到很多麻烦。拥有完整对称矩阵,你就不必担心顺序问题,而且向量化非常顺畅。

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