R:如何在没有循环或更高效的情况下进行矩阵运算?

时间:2014-07-14 01:25:55

标签: r matrix

我正在尝试制作这个操作矩阵,将第一列乘以2,3和4,第一个保持值,然后将第二列乘以3和4,保持第三列的值并乘以第三列我希望在不使用“for”循环的情况下执行此操作,希望使用sapply或mapply等函数。有没有人知道怎么做?

一行示例:

a[1,1]*(a[1,2], a[1,3], a[1,4]) = 2 4 4 4
a[1,1] a[1,2]*(a[1,3], a[1,4]) = 2 4 16 16 #keep a[1,1] a[1,2] 
a[1,1] a[1,2] a[1,3] a[1,3]*(a[1,4]) = 2 4 16 256 # #keep a[1,1] a[1,2] a[1,3] 

输入:

> a<- matrix(2,4,4) # or any else matrix like a<- matrix(c(1,8,10,1,4,1),3,3)
> a
     [,1] [,2] [,3] [,4]
[1,]    2    2    2    2
[2,]    2    2    2    2
[3,]    2    2    2    2
[4,]    2    2    2    2

输出:

> a
     [,1] [,2] [,3] [,4]
[1,]    2    4    16    256
[2,]    2    4    16    256
[3,]    2    4    16    256
[4,]    2    4    16    256

编辑:循环版本

a<- matrix(2,4,4); 
ai<-a[,1,drop=F]; 
b<- matrix(numeric(0),nrow(a),ncol(a)-1); 

i<- 1; 

for ( i in 1:(ncol(a)-1)){ 

  a<- a[,1]*a[,-1,drop=F]; 
  b[,i]<- a[,1]; 

}

b<- cbind(ai[,1],b); 

b

enter image description here

1 个答案:

答案 0 :(得分:3)

如果我理解正确,你要做的是,从带有N列的矩阵A开始,执行以下步骤:

步骤1.将A的第2列到第A列乘以A的第1列。调用生成的矩阵A1。

步骤2.将A1的第3列到第N列乘以A1的第2列。调用生成的矩阵A2。

...

步骤(N-1)。将A(N-2)的列N乘以A(N-2)的列(N-1)。这是理想的结果。

如果这确实是你想要做的,你需要写一个双for循环(你想要避免,如你所说)或者想出一些执行上述步骤的迭代方法

for方式看起来像这样

DoubleFor <- function(m) {
    res <- m
    for(i in 1:(ncol(res)-1)) {
        for(j in (i+1):ncol(res)) {
            res[, j] <- res[, i] * res[, j]
        }
    }
    res
}

使用R的矢量化操作,可以避免内部for循环

SingleFor <- function(m) {
    res <- m
    for(i in 1:(ncol(res)-1)) 
        res[, (i+1):ncol(res)] <- res[, i] * res[, (i+1):ncol(res)]
    res
}

在迭代过程时,您可能希望定义递归函数,或使用Reduce。递归函数类似于

RecursiveFun <- function(m, i = 1) {
    if (i == ncol(m)) return(m)
    n <- ncol(m)
    m[, (i+1):n] <- m[, (i+1):n] * m[, i]
    Recall(m, i + 1) # Thanks to @batiste for suggesting using Recall()!
}

虽然Reduce将使用类似的函数而没有递归(由Reduce提供)

ReduceFun <- function(m) { 
    Reduce(function(i, m) {
            n <- ncol(m)
            m[, (i+1):n] <- m[, (i+1):n] * m[, i]
            m
        }, c((ncol(m)-1):1, list(m)), right = T)
}

这些都会产生相同的结果,例如:测试你的矩阵

a <- matrix(c(1, 8, 10, 1, 4, 1), 3, 3)
DoubleFor(a)
#      [,1] [,2] [,3]
# [1,]    1    1    1
# [2,]    8   32 2048
# [3,]   10   10 1000
all(DoubleFor(a) == SingleFor(a) & SingleFor(a) == RecursiveFun(a) & 
    RecursiveFun(a) == ReduceFun(a))
# [1] TRUE

出于好奇,我做了一个快速的速度比较,但我不认为上面的任何一个会比你的其他任何一个明显快于你的矩阵大小,所以我会选择你那个认为更具可读性。

a <- matrix(rnorm(1e6),  ncol = 1e3)
system.time(DoubleFor(a))
#    user  system elapsed 
#  22.158   0.012  22.220 
system.time(SingleFor(a))
#    user  system elapsed 
#  27.349   0.004  27.415 
system.time(RecursiveFun(a))
#    user  system elapsed 
#  25.150   1.336  26.534 
system.time(ReduceFun(a))
#    user  system elapsed 
#  26.574   0.004  26.626