2014-10-22 3 views
0

У меня возникла следующая проблема: у меня есть матрица, которая равна 20 x 1000, и я хочу разделить ее на четыре подматрицы размером 20 x 250.Индексация подматрицы и операции без циклов

После этого я хочу сделать операцию для каждой подматрицы предположить, что у меня есть вектор P длина, равной числу подматрицы, 4.

P= [ 3 4 5 6] 

к чему я стремлюсь, чтобы сделать для каждой подматрицы (а) состоит в следующем:

Для первой подматрицы: A(:,1:P(1))=1

Как и вторая подматрица: A(:,1:P(2))=1 и так далее и тому подобное.

Как я мог сделать это без циклов?

+0

Любые замечания по подходам, упомянутым в единственном решении, представленном здесь ? – Divakar

ответ

0

Один Векторизованных подход может быть комбинацией cumsum и bsxfun, которые могли бы быть немного памяти интенсивно, хотя -

blocksize = 250; 
valid_idx = bsxfun(@le,[1:max(P)],P'); 
idx_mat = bsxfun(@plus,cumsum(valid_idx,2),[0:numel(P)-1]'*blocksize); 
A(:,idx_mat(valid_idx)) = 1; %// You can replace this with "A(:,unique(idx_mat))=1;" 

Еще несколько иной подход -

blocksize = 250; 
maxP = max(P); 
valid_idx = bsxfun(@le,[1:maxP],P'); 
idx_mat = bsxfun(@plus,[0:numel(P)-1]'*blocksize,1:maxP); 
A(:,idx_mat(valid_idx))=1; 

Пожалуйста, обратите внимание, чтобы действительно увидеть преимущества векторизованных решений, вам нужно использовать их, когда ваш исходный код цикла имеет много итераций goin г. В противном случае накладные расходы, связанные с подготовительной работой по настройке векторизованных подходов, будут отходами. Таким образом, я предполагаю, что ваш фактический случай включает в себя не более 4 подматриц.


Другой cumsum подход, основанный, и это один должно быть интересно попробовать и даже может оказаться лучшим из партии -

blocksize = 250; 

%//Get monotonically increasing labels within each group, defined by limits from idx 
array1 = zeros(1,sum(P)); 
grp_starts = cumsum(P(1:end-1))+1; 
array1(grp_starts) = P(1:end-1); 
grp_labels = [1:numel(array1)] - cumsum(array1); 

%// Get offsetted indices 
array2 = zeros(1,sum(P)); 
array2(grp_starts) = blocksize; 
offsetted_grp_labels = grp_labels + cumsum(array2); 

A(:,offsetted_grp_labels)=1; %// perform the operation(s) 
+0

спасибо Divakar за вашу помощь ... я попробую ваше предложение и скажу вам – user3628544