【问题标题】:How to vectorize this operation?如何向量化这个操作?
【发布时间】:2021-09-02 13:11:01
【问题描述】:

我有一个 n x 3 x m 数组,称之为 I。它包含 3 列、n 行(例如 n=10)和 m 个切片。我有一个必须完成的计算,以根据切片中的其他 2 列替换每个切片中的第三列。

我编写了一个函数 insertNewRows(I[,,simIndex]),它采用给定的切片并替换第三列。下面的 for 循环可以满足我的要求,但速度很慢。 有没有办法通过使用其中一个应用函数来加快速度?我不知道如何让它们以我想要的方式工作。

for(simIndex in 1:m){
     I[,, simIndex] = insertNewRows(I[,,simIndex])
}

如果需要,我可以提供有关 insertNewRows 的更多详细信息,但简短的版本是它采用基于给定数组切片的列 I[,1:2, simIndex] 的概率,并生成基于二项式 RV关于概率。

似乎其中一个应用功能应该通过使用来工作 I = apply(FUN = insertNewRows, MARGIN = c(1,2,3)) 但这只会产生乱码..?

提前感谢您! IK

【问题讨论】:

  • 如果您可以向我们提供可复制的minimal working example,我们可以复制和粘贴以更好地了解问题并测试可能的解决方案,这将很有帮助。您可以使用dput(YOUR_DATASET) 共享数据集,或者使用dput(head(YOUR_DATASET)) 共享较小的样本。 (请参阅this answer 以获得一些很好的建议。)

标签: r for-loop vectorization apply


【解决方案1】:

这个问题没有定义输入、转换和结果,所以我们不能真正回答它,但这里有一个例子,为每个 i 添加一行到 a[,,i] 所以也许这会建议您如何自己解决问题。

这就是您可以使用 sapply、apply、plyr::aaply、使用 matrix/aperm 和 abind::abind 进行整形的方式。

# input array and function
a <- array(1:24, 2:4)
f <- function(x) rbind(x, 1)  # append a row of 1's

aa <- array(sapply(1:dim(a)[3], function(i) f(a[,,i])), dim(a) + c(1,0,0))
aa2 <- array(apply(a, 3, f), dim(a) + c(1,0,0))
aa3 <- aperm(plyr::aaply(a, 3, f), c(2, 3, 1))
aa4 <- array(rbind(matrix(a, dim(a)[1]), 1), dim(a) + c(1,0,0))
aa5 <- abind::abind(a, array(1, dim(a)[2:3]), along = 1)

dimnames(aa3) <- dimnames(aa5) <- NULL 
sapply(list(aa2, aa3, aa4, aa5), identical, aa)
## [1] TRUE TRUE TRUE TRUE

aa[,,1]
##      [,1] [,2] [,3]
## [1,]    1    3    5
## [2,]    2    4    6
## [3,]    1    1    1

aa[,,2]
##      [,1] [,2] [,3]
## [1,]    7    9   11
## [2,]    8   10   12
## [3,]    1    1    1

aa[,,3]
##      [,1] [,2] [,3]
## [1,]   13   15   17
## [2,]   14   16   18
## [3,]    1    1    1

aa[,,4]
##      [,1] [,2] [,3]
## [1,]   19   21   23
## [2,]   20   22   24
## [3,]    1    1    1

【讨论】:

  • 谢谢!我认为这基本上可以满足我的需求。你能告诉我一点关于 1:4 和 c(3,3,4) 在 aa 的作业中做了什么吗?似乎 1:4 给出了为 i 插入的索引,对吗?然后 c(3,3,4) 给出了新数组的维度,并附加了 1 的行?如果是这样,这几乎正是我所需要的!
  • 我已经替换了硬编码项目以使其更易于理解并添加了第 4 种方法。
  • 添加了另一个解决方案。
猜你喜欢
  • 2020-01-10
  • 1970-01-01
  • 2013-12-28
  • 1970-01-01
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 1970-01-01
  • 2013-03-12
相关资源
最近更新 更多