设A是n * n对角矩阵。说,n = 5:
A <- diag(1, 5)
A
[,1] [,2] [,3] [,4] [,5]
[1,] 1 0 0 0 0
[2,] 0 1 0 0 0
[3,] 0 0 1 0 0
[4,] 0 0 0 1 0
[5,] 0 0 0 0 1
我需要按行随机化A
,使1离开对角线。我想出了这个解决方案:
n <- 5
count <- c(1:n)
for (i in count) {
while (A[count[i], count[i]] == 1) { #avoid 1 in diagonal
A[count[i],] <- sample(A[count[i],]) #permutes ith row
}
}
但我很确定应该有一种更有效的方法。谢谢你的关注。
答案 0 :(得分:5)
您可以从整数序列1:n
中抽样一个随机数,n
次,但每次都会排除与对角线对应的单元格编号。
执行此操作的一种方法如下:
n <- 5
rnd <- sample(n-1, repl=T)
i <- c(rnd + (rnd >= seq_len(n-1)) * 1, sample(n-1, 1))
i
# [1] 3 3 4 5 1
这里,i
的每个元素被阻止等于元素的索引(例如,元素1不能是1,元素2不能是2,等等)。我们可以将i
的每个元素依次视为每行的选定列。
接下来,我们设置一个零矩阵,并且(对于上面的示例)填充单元格[1, 3]
,[2, 3]
,[3, 4]
,[4, 5]
和{{1}到1。
[5, 1]
最后一行代码使用矩阵子集将矩阵m <- matrix(0, nc=n, nr=n)
m[cbind(seq_len(n), i)] <- 1
m
# [,1] [,2] [,3] [,4] [,5]
# [1,] 0 0 1 0 0
# [2,] 0 0 1 0 0
# [3,] 0 0 0 1 0
# [4,] 0 0 0 0 1
# [5,] 1 0 0 0 0
子集化到相关的单元格。
修改强>
为了确保每一列和每行只有一个m
,并且这些列保持在对角线之外,以下向量化方法将起作用。这里的技巧是置换向量1
,并将该置换向量的每个元素视为我们将分配的n-1
非对角元素的每一行的索引{{1} }。然后,对于我们的置换向量的每个元素,我们检查该值是否小于相应行的对角线的索引。如果是这样,我们将元素保留为原样,否则我们添加1.这将确定第一个n-1
行的列索引。最后一行的索引就是那个还没有1
的列的索引。
n-1
答案 1 :(得分:1)
不确定这是最好的还是最优雅的,但你可以选择一个随机(但非对角线)元素来替换每一行上的对角线元素,然后为非对角线分配剩余部分:
count <- c(1:n)
for (i in count) {
off <- sample(count[-i],1)
perm <- sample(count[-off])
tmp <- A[i,off]
A[i, count[-i]] <- A[i,perm]
A[i,i] <- tmp
}