Помещение последовательности в матрицу вокруг существующих значений - PullRequest
2 голосов
/ 07 июня 2019

Я хочу сгенерировать симметричную матрицу вокруг диагонали нулей и заданной последовательности вокруг них. Теоретически линии должны отображаться как

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 ]

1 голос
/ 07 июня 2019

Есть более простой способ сделать то, что вам нужно.Вы можете начать с создания matrix из length(x) + 1 столбцов и строк со всеми элементами в виде логического TRUE.Затем сделайте диагональ FALSE, используя diag().Теперь вы можете заменить TRUE s на нужный вам вектор.На диагональ 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 медленнее, вероятно, потому что он создает матричные элементы по одной строке за раз и вызывает append для каждой строки,Все эти издержки избегаются при make_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
0 голосов
/ 07 июня 2019

Использование простой 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

data

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