R:如何在没有for循环的情况下分配A [B [,j],j]

时间:2016-09-18 13:34:24

标签: r for-loop matrix vectorization assign

我希望将矩阵A中的某些值替换为另一个值:1。对于A的第j列,需要替换的行索引是B的第j th 列中的行索引。下面我举一个例子,其中赋值是通过for循环实现的。

我的问题是:如何更简单,更有效和/或没有for循环实现这项任务?

set.seed(4521)
n <- 10
p <- 5

A <- matrix(rep(NaN,n*p),n,p)

B <- replicate(p, sample(n))
B <- B[1:5,]

for (j in 1:n){      
  A[B[,j],j] <- 1      
}

print(B)
print(A)

B

      [,1] [,2] [,3] [,4] [,5]
[1,]    5   10    7    6    5
[2,]   10    2    9    9    2
[3,]    7    9    3   10    4
[4,]    9    4    1    3    3
[5,]    4    8    6    4    9

A

        [,1] [,2] [,3] [,4] [,5]
 [1,]   NaN  NaN    1  NaN  NaN
 [2,]   NaN    1  NaN  NaN    1
 [3,]   NaN  NaN    1    1    1
 [4,]     1    1  NaN    1    1
 [5,]     1  NaN  NaN  NaN    1
 [6,]   NaN  NaN    1    1  NaN
 [7,]     1  NaN    1  NaN  NaN
 [8,]   NaN    1  NaN  NaN  NaN
 [9,]     1    1    1    1    1
 [10,]    1    1  NaN    1  NaN

3 个答案:

答案 0 :(得分:4)

我们可以使用矩阵索引:

i <- as.numeric(B)
j <- rep(1:ncol(B), each = nrow(B))
A[cbind(i,j)] <- 1

或者将它们放在一行中:

A[cbind(as.numeric(B), rep(1:ncol(B), each = nrow(B)))] <- 1

正如OP稍后通过一些挖掘自己所说,我们可以用更短的rep(1:ncol(B), each = nrow(B))替换as.numeric(col(B))。我知道但我从来没有这样做,因为它使用的内存是我建议的内存的两倍。使用哪一个只是个人偏好。只有在处理大型矩阵时才有意义。

答案 1 :(得分:2)

恕我直言,@ Zheyuan Li的代码正在做的更清楚。我更喜欢他的解决方案 只是为了显示一个替代方案:使用1D索引,您可以这样做:

An <- nrow(A)
Bp <- ncol(B)
offset <- rep(seq(0, An*(Bp-1), by=An), each=Bp)
A[B + offset] <- 1

在一行中:

A[B + rep(seq(0, nrow(A)*(ncol(B)-1), by=nrow(A)), each=ncol(B))] <- 1

答案 2 :(得分:0)

简单的解决方案:

world

感谢(和+1)在Zheyuan Li的第一个答案中输入了col而不是A[cbind(as.numeric(B), as.numeric(col(B)))] <- 1