2016-05-10 4 views
4

Я хотел бы вставить столбцы в матрицу, но позиции вставки столбца в матрице отличаются по строкам. Как я могу это сделать без использования for-loop?Вставка столбцов в матрицу в Matlab

Ниже приведен упрощенный пример в MATLAB; Из A, X, P, я хочу получить APX без использования for-loop.

>> A = zeros(4,5)  % inclusive matrix 

A = 
    0 0 0 0 0 
    0 0 0 0 0 
    0 0 0 0 0 
    0 0 0 0 0 

>> X = [9,8;5,7;8,3;6,7] % data to insert 

    X = 
    9 8 
    5 7 
    8 3 
    6 7 

>> P = [3;2;4;1] % insertion position within the matrix 

P = 
    3 
    2 
    4 
    1 

>> APX = [0,0,9,8,0;0,5,7,0,0;0,0,0,8,3;6,7,0,0,0] % what I want 

    APX = 
    0 0 9 8 0 
    0 5 7 0 0 
    0 0 0 8 3 
    6 7 0 0 0 
+1

Что не так с использованием for-loop? – ToBe

+0

Векторизованные коды намного быстрее, чем векторы с петлями в Matlab, особенно когда размеры матрицы довольно большие; т. е. тысячи х тысяч –

+3

@HyungDonLee. Вы действительно должны попробовать использовать циклы, прежде чем пытаться его векторизовать. MATLAB R2015b имеет улучшенный двигатель JIT, где петли теперь конкурентоспособны. – rayryeng

ответ

6

Это просто определение правильных индексов столбца для доступа к матрице, чтобы вы могли заполнить его желаемыми значениями. Для этого сначала необходимо создать правильные значения строк и столбцов для доступа к правильным позициям в APX, чтобы вы могли использовать X для заполнения этих позиций.

Используя P, каждый элемент сообщает вам, какой столбец вы должны начать заполнять для каждой строки X. Вам нужно будет генерировать индексы столбцов в порядке возрастания до такого количества столбцов, как в X. Чтобы сгенерировать индексы строк, просто создайте матрицу, размер которой равен X, где каждый столбец занимает от 0 до нескольких строк, как есть в X минус 1 (то есть 0:size(X,2)-1). Эта матрица дает правильные смещения, чтобы вы могли принять P и добавить ее с помощью этой матрицы. Как только вы это сделаете, у вас будет индексная матрица столбца, в которой вы конкретно укажете, где каждый элемент должен идти в отношении столбцов выходной матрицы в строке P. Наконец, используйте sub2ind для генерации индексов столбца с использованием строков и столбцов, сгенерированных выше, для размещения X в APX.

Других слова:

P = [3;2;4;1]; 
X = [9,8;5,7;8,3;6,7]; 

rowInd = repmat((1:size(X,1)).', 1, size(X,2)); %' 
colInd = bsxfun(@plus, P, 0:size(X,2)-1); 
APX = zeros(size(X,1), max(colInd(:))); 
APX(sub2ind(size(APX), rowInd, colInd)) = X; 

для генерации строки местоположения, мы используем repmat, чтобы создать матрицу, которая имеет такой же размер, как X, где каждый столбец охватывает от 1 до стольких строк, сколько X. Чтобы создать расположение столбцов, мы используем bsxfun для создания матрицы, где каждый столбец является вектором P, но увеличивается на 1 на столбец. Затем мы создаем APX, чтобы быть совместимого размера, затем используйте sub2ind, чтобы окончательно заполнить матрицу.

С вашими выше тестовых входов, мы получаем:

APX = 

    0  0  9  8  0 
    0  5  7  0  0 
    0  0  0  8  3 
    6  7  0  0  0 

Minor Примечание

Вы действительно должны фактически попытаться использовать петли, прежде чем пытаться его векторизации. Хотя в предыдущих версиях MATLAB использование циклов было медленным, MATLAB R2015b имеет улучшенный JIT-движок, где петли теперь конкурентоспособны. Вы должны время, чтобы ваш код использовал циклы и гарантировал, что это оправданно, прежде чем переключиться на векторизованные реализации.

+0

В этом случае 'repmat' лучше, чем' meshgrid', или 'bsxfun (@plus, нули (1, размер (X, 2)) ', 1: размер (X, 1)).'?? –

+0

@StewieGriffin Я не рассматривал 'meshgrid', потому что он выводит две переменные ... Я считаю это расточительным. Я решил, что «repmat» будет более консервативным с ресурсами. – rayryeng

+0

Я предполагаю, что это [проверено] (http://stackoverflow.com/a/29753104/2338750). –