Как назначить значения по диагонали?

40

Предположим, что у меня есть матрица NxN A, индексный вектор V, состоящий из подмножества чисел 1: N и значения K, и я хочу сделать это:

 for i = V
     A(i,i) = K
 end

Есть ли способ сделать это в одном утверждении w/vectorization?

например. A (что-то) = K

Оператор A(V,V) = K не будет работать, он назначает недиагональные элементы, и это не то, что я хочу. например:.

>> A = zeros(5);
>> V = [1 3 4];
>> A(V,V) = 1

A =

 1     0     1     1     0
 0     0     0     0     0
 1     0     1     1     0
 1     0     1     1     0
 0     0     0     0     0
  • 0
    Джейсон: Обратите внимание, что нам не нужно добавлять «MATLAB» в заголовок вопроса, так как он уже указан в тегах. Руководящие принципы SO препятствуют дублированию информации в заголовке и тегах.
Теги:
vectorization

5 ответов

55
Лучший ответ

Я обычно использую EYE для этого:

A = magic(4)
A(logical(eye(size(A)))) = 99

A =
    99     2     3    13
     5    99    10     8
     9     7    99    12
     4    14    15    99

В качестве альтернативы вы можете просто создать список линейных индексов, так как от одного диагонального элемента до следующего он принимает шаги nRows+1:

[nRows,nCols] = size(A);
A(1:(nRows+1):nRows*nCols) = 101
A =
   101     2     3    13
     5   101    10     8
     9     7   101    12
     4    14    15   101

Если вы хотите получить доступ к подмножеству диагональных элементов, вам необходимо создать список диагональных индексов:

subsetIdx = [1 3];
diagonalIdx = (subsetIdx-1) * (nRows + 1) + 1;
A(diagonalIdx) = 203
A =
   203     2     3    13
     5   101    10     8
     9     7   203    12
     4    14    15   101

В качестве альтернативы вы можете создать логический индексный массив с помощью diag (работает только для квадратных массивов)

diagonalIdx = false(nRows,1);
diagonalIdx(subsetIdx) = true;
A(diag(diagonalIdx)) = -1
A =
    -1     2     3    13
     5   101    10     8
     9     7    -1    12
     4    14    15   101
  • 0
    круто, это работает! примет, когда закончится тупой таймер
  • 0
    @ Джейсон С: Спасибо! Я на самом деле считаю это раздражающим вопросом; Я часто пытаюсь использовать diag , прежде чем я помню, как использовать eye
Показать ещё 4 комментария
20
>> tt = zeros(5,5)
tt =
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
>> tt(1:6:end) = 3
tt =
     3     0     0     0     0
     0     3     0     0     0
     0     0     3     0     0
     0     0     0     3     0
     0     0     0     0     3

и более общий:

>> V=[1 2 5]; N=5;
>> tt = zeros(N,N);
>> tt((N+1)*(V-1)+1) = 3
tt =
     3     0     0     0     0
     0     3     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     3

Это основано на том, что к матрицам можно обращаться как к одномерным массивам (векторам), где 2 индекса (m, n) заменяются линейным отображением m * N + n.

  • 0
    Я увидел ваше решение только после того, как отправил свою правку. +1 за то, что быстрее, хотя мое решение немного более общее :)
  • 1
    Мне очень нравится метод tt (1: n + 1: end), действительно чистый!
Показать ещё 1 комментарий
2

Предположим, что K - значение. Команда

A=A-diag(K-diag(A))

может быть немного быстрее

>> A=randn(10000,10000);

>> tic;A(logical(eye(size(A))))=12;toc

Истекшее время - 0,517575 секунд.

>> tic;A=A+diag((99-diag(A)));toc

Истекшее время составляет 0.353408 секунд.

Но он потребляет больше памяти.

  • 0
    Я использовал A(logical(eye(size(A))))=K гибкий, быстрый и надежный
2
A = zeros(7,6);
V = [1 3 5];

[n m] = size(A);
diagIdx = 1:n+1:n*m;
A( diagIdx(V) ) = 1

A =
     1     0     0     0     0     0
     0     0     0     0     0     0
     0     0     1     0     0     0
     0     0     0     0     0     0
     0     0     0     0     1     0
     0     0     0     0     0     0
     0     0     0     0     0     0
1

Я бы использовал sub2ind и передавал диагональные индексы в качестве параметров x и y:

A = zeros(4)
V=[2 4]

idx = sub2ind(size(A), V,V)
% idx = [6, 16]

A(idx) = 1

% A =
% 0     0     0     0
% 0     1     0     0
% 0     0     0     0
% 0     0     0     1

Ещё вопросы

Сообщество Overcoder
Наверх
Меню