I have three matrices:
Values = [200x7] doubles
numOfStrings = [82 78 75 73 72 71 70] %(for example)
numOfColumns = [1 4]
The numOfColumns
may contain any set of distinct values from 1 to 7. For example [1 2 3]
or [4 7]
or [1 5 6 7]
. Obviously, biggest numOfColumns
that can be is [1 2 3 4 5 6 7]
.
numOfColumns
show the columns I want to get. numOfStrings
shows the rows of that columns I need. I.e. in my example I want to get columns 1
and 4
. So from the 1
column I want to get the 82
first rows and from the 4th
get the 73
first rows.
i.e. if numOfColumns = [1 4]
then
myCell{1} = Values( 1:82,1); % Values(numOfStrings(numOfColumn(1)), numOfColumn(1))
myCell{2} = Values( 1:73,4); % Values(numOfStrings(numOfColumn(2)), numOfColumn(2))
P.S. That's not necessary to save it into cell array. If you can offer any another solution Ill be grateful to you.
I'm looking for the fastest way to do this, which is likely to be by avoiding for
loops and using vectorization.
I think a lot about sub2ind
function. But I can't figure out how to return arrays of the different size! Because myCell{1} - [82x1]
and myCell{2} - [73x1]
. I suppose I can't use bsxfun
or arrayfun
.
RESULTS:
Using for
loops alike @Will 's answer:
for jj = 1:numel(numOfColumns)
myCell{rowNumber(numOfColumns(jj)),numOfColumns(jj)} = Values( 1:numOfStrings(numOfColumns(jj)),numOfColumns(jj));
end
Elapsed time is 157 seconds
Using arrayfun
alike @Yishai E 's answer:
myCell(sub2ind(size(myCell),rowNumber(numOfColumns),numOfColumns)) = arrayfun( @(nOC) Values( 1:numOfStrings(nOC),nOC), numOfColumns, 'UniformOutput', false);
Elapsed time is 179 seconds
Using bsxfun
alike @rahnema1 's answer:
idx = bsxfun(@ge,numOfStrings , (1:200).');
extracted_values = Values (idx);
tempCell = mat2cell(extracted_values,numOfStrings);
myCell(sub2ind(size(myCell),rowNumber(numOfColumns),numOfColumns)) = myCell(numOfColumns)';
Elapsed time is 204 seconds
SO, I got a lot of working answers, and some of them are vectorized as I asked, but for
loops still fastest!
% Get number of elements in NUMOFCOLUMNS
n = numel(numOfColumns);
% Set up output
myCell = cell(1,n);
% Loop through all NUMOFCOLUMNS values, storing to cell
for i = 1:n
myCell{i} = Values(1:numOfStrings(numOfColumns(i)), numOfColumns(i));
end
Which for your example gives output
myCell =
[82x1 double] [73x1 double]