随机化二进制对角矩阵的最佳方法,保持1对角线不对称

时间:2014-04-30 09:42:28

标签: r permutation

设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
  }
}

但我很确定应该有一种更有效的方法。谢谢你的关注。

2 个答案:

答案 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
}