Iml*_*ith 1 performance r matrix mapply
我想一个函数应用于矩阵的输入a,这个功能将改变第一个元素c[a[1]]和下一个元素,b[a[i],a[i+1]]从开始i = 1达i = ncol(a) - 1.
示例输入:
a <- matrix(c(1,4,3,1),nrow=1)
b <- matrix(1:25,ncol=5,nrow=5)
c <- matrix(4:8,ncol=5,nrow=1)
Run Code Online (Sandbox Code Playgroud)
预期产量:
>a
4 16 14 3
#c[a[1]] gave us the first element: 4
#b[a[1],a[2]] gave us the second element: 16
#b[a[2],a[3]] gave us the third element: 14
#b[a[3],a[4]] gave us the fourth element: 3
Run Code Online (Sandbox Code Playgroud)
mapply()到目前为止,我一直试图使用但没有任何成功.这个想法是避免循环,因为这些东西会导致R的主要性能下降
步骤1:使用单个索引寻址矩阵
在R矩阵中,元素按列主要顺序存储到向量中,因此A[i, j]也是如此A[(j-1)*nrow(A) + i].考虑随机3乘3矩阵的示例:
set.seed(1); A <- round(matrix(runif(9), 3, 3), 2)
> A
[,1] [,2] [,3]
[1,] 0.27 0.91 0.94
[2,] 0.37 0.20 0.66
[3,] 0.57 0.90 0.63
Run Code Online (Sandbox Code Playgroud)
现在,这个矩阵有3行(nrow(A) = 3).相比:
A[2,3] # 0.66
A[(3-1) * 3 + 2] # 0.66
Run Code Online (Sandbox Code Playgroud)
第2步:矢量化
您可以一次处理矩阵的多个元素.但是,您只能通过使用单个索引模式来执行此操作(此处不太精确,请参阅@ alexis_laz之后的评论).例如,如果要提取A[1,2]和A[3,1],但如果这样做:
A[c(1,3), c(2,1)]
# [,1] [,2]
# [1,] 0.91 0.27
# [2,] 0.90 0.57
Run Code Online (Sandbox Code Playgroud)
你实际上得到了一个阻止.现在,如果您使用单个索引,您将获得所需:
A[3 * (c(2,1) - 1) + c(1,3)]
# [1] 0.91 0.57
Run Code Online (Sandbox Code Playgroud)
第3步:获取问题的单一索引
假设n <- length(a)并且您想要解决以下元素b:
a[1] a[2]
a[2] a[3]
. .
. .
a[n-1] a[n]
Run Code Online (Sandbox Code Playgroud)
你可以使用单一索引nrow(b) * (a[2:n] - 1) + a[1:(n-1)].
第4步:完成解决方案
因为你只有单排a和c,你应该将它们存储为向量,而不是矩阵.
a <- c(1,4,3,1)
c <- 4:8
Run Code Online (Sandbox Code Playgroud)
如果给你一个矩阵而没有选择(因为它们目前在你的问题中),你可以通过以下方式将它们转换为向量:
a <- as.numeric(a)
c <- as.numeric(c)
Run Code Online (Sandbox Code Playgroud)
现在,如上所述,我们有地址b矩阵的索引:
n <- length(a)
b_ind <- nrow(b) * (a[2:n] - 1) + a[1:(n-1)]
Run Code Online (Sandbox Code Playgroud)
您还将a[1]元素c作为最终结果的第一个元素,因此我们需要连接:c[a[1]]并且b[b_ind]:
a <- c(c[a[1]], b[b_ind])
# > a
# [1] 4 16 14 3
Run Code Online (Sandbox Code Playgroud)
这种方法完全矢量化,甚至比*apply家庭更好.
alexis_laz的评论
alexis_laz提醒我,我们也可以使用"矩阵索引",即我们也可以b通过以下方式处理矩阵:
b[cbind(a[1:(n-1)],a[2:n])] ## or b[cbind(a[-n], a[-1])]
Run Code Online (Sandbox Code Playgroud)
但是,我认为使用单个索引稍微快一点,因为我们需要逐行访问索引矩阵以便解决b,因此我们支付的内存延迟比使用矢量索引更高.
| 归档时间: |
|
| 查看次数: |
208 次 |
| 最近记录: |