将序列放入现有值周围的矩阵中

时间:2019-06-06 23:04:46

标签: r matrix seq

我想围绕零的对角线和围绕它们的预定序列生成对称矩阵。理论上,这些行应显示为

0 1 3 5 7 9
1 0 3 5 7 9

我已经尝试过调整条件,但是我怀疑由于索引的原因,它是很奇怪的,我尚不足以解决这个问题。

bend <- function(n){
  m <- seq(1, n, by=2)
  a <- length(m)
  y <- matrix(nrow= a, ncol = a, byrow= TRUE)
  y <- ifelse(row(y) == col(y), 0, m)
  y
}

假设输入为9,预期输出为

0 1 3 5 7 9    
1 0 3 5 7 9 
1 3 0 5 7 9    
1 3 5 0 7 9    
1 3 5 7 0 9    
1 3 5 7 9 0

实际输出为

0 3 5 7 9 1    
3 0 7 9 1 3    
5 7 0 1 3 5    
7 9 1 0 5 7    
9 1 3 5 0 9    
1 3 5 7 9 0

2 个答案:

答案 0 :(得分:1)

有一种更简单的方法可以满足您的需求。您可以通过创建matrix的{​​{1}}列和行中的length(x) + 1来开始,并将所有元素作为逻辑TRUE。然后使用FALSE制作对角线diag()。现在,您可以将TRUE替换为所需的向量。对角线FALSE不受影响。由于这些值是逐列替换的,因此需要最后的转置t()才能获得正确的结果。

这样,您不必担心跟踪索引。

x <- c(1,3,5,7,9)

make_matrix <- function(x) {
  m <- matrix(TRUE, ncol = length(x) + 1, nrow = length(x) + 1)
  diag(m) <- FALSE
  m[m] <- x
  t(m)
}

make_matrix(x)

     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    0    1    3    5    7    9
[2,]    1    0    3    5    7    9
[3,]    1    3    0    5    7    9
[4,]    1    3    5    0    7    9
[5,]    1    3    5    7    0    9
[6,]    1    3    5    7    9    0

这是sapply的另一种方式。这将在每次迭代中创建必要的行元素,并将它们逐列放置在矩阵中。同样,您需要t()才能获得正确的结果。 -

sapply(0:length(x), function(a) append(x, 0, after = a)) %>% t()

     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    0    1    3    5    7    9
[2,]    1    0    3    5    7    9
[3,]    1    3    0    5    7    9
[4,]    1    3    5    0    7    9
[5,]    1    3    5    7    0    9
[6,]    1    3    5    7    9    0

基准-

sapply较慢,可能是因为它一次创建一行矩阵元素,并为每一行调用appendmake_matrix()方法避免了所有这些开销。

x <- sample(100)

microbenchmark(
  make_matrix = make_matrix(x),
  sapply = t(sapply(0:length(x), function(a) append(x, 0, after = a))),
  akrun_forloop = {
    n <- length(x) + 1
    m1  <- matrix(0, n, n)
    for(i in seq_len(nrow(m1))) m1[i, -i] <- x
  },
  times = 1000
)

Unit: microseconds
          expr      min        lq      mean   median        uq       max neval
   make_matrix  111.495  117.5610  128.3135  126.890  135.7540   225.323  1000
        sapply  520.620  551.1765  592.2642  573.335  602.2585 10477.221  1000
 akrun_forloop 3380.292 3526.3080 3837.1570 3648.765 3812.5075 20943.245  1000

答案 1 :(得分:0)

使用简单的for循环

n <- length(x) + 1
m1  <- matrix(0, n, n)
for(i in seq_len(nrow(m1))) m1[i, -i] <- x
m1
#     [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]    0    1    3    5    7    9
#[2,]    1    0    3    5    7    9
#[3,]    1    3    0    5    7    9
#[4,]    1    3    5    0    7    9
#[5,]    1    3    5    7    0    9
#[6,]    1    3    5    7    9    0

数据

x <- c(1,3,5,7,9)