Замена элементов матрицы, индексированных другой матрицей

#r #loops #matrix #apply

#r #циклы #матрица #применить

Вопрос:

После нескольких часов поиска я обращаюсь к вашему опыту. Новичок в R, я пытаюсь ускорить свой код. Моя цель — заменить значения в матрице A . Однако я хочу заменить значения на основе двух векторов другой матрицы B . B[, 1] — это имя строки i матрицы A . Второй столбец B[, 2] соответствует имени столбца матрицы A .

Первая версия моего кода заключалась в использовании функции сопоставления в цикле.

 for(k in 1:L){
  i <- B[k,1]
  j <- B[k,2]
  d <- match(i,rownames(A))
  e <- match(j,colnames(A))
  A[d, e] <- 0
  }
  

Вторая версия позволила мне немного ускорить:

 for( k in 1:L) {
  A[match(B[k,1],rownames(A)), match(B[k,2],colnames(A))] <- 0
  }
  

Однако время обработки велико, слишком велико. Поэтому я решил использовать apply функцию. Для этого я должен использовать apply в каждой строке векторы B .

Является ли использование apply функции отличным способом? Или я иду не тем путем?

Ответ №1:

Мне кажется, что вы можете просто сделать A[B[, 1:2]] <- 0 , используя возможности индексации матрицы.

Например, A[cbind(1:4, 1:4)] <- 0 заменит A[1,1] , A[2,2] , A[3,3] и A[4,4] на 0 . Фактически, if A имеет атрибуты «dimnames» («имена строк» и «имена столбцов», на которые вы ссылаетесь), мы также можем использовать символьные строки в качестве индекса.


Воспроизводимый пример

 A <- matrix(1:16, 4, 4, dimnames = list(letters[1:4], LETTERS[1:4]))
#  A B  C  D
#a 1 5  9 13
#b 2 6 10 14
#c 3 7 11 15
#d 4 8 12 16

set.seed(0); B <- cbind(sample(letters[1:4])), sample(LETTERS[1:4]))
#     [,1] [,2]
#[1,] "d"  "D" 
#[2,] "a"  "A" 
#[3,] "c"  "B" 
#[4,] "b"  "C" 

## since `B` has just 2 columns, we can use `B` rather than `B[, 1:2]`
A[B] <- 0

#  A B  C  D
#a 0 5  9 13
#b 2 6  0 14
#c 3 0 11 15
#d 4 8 12  0