define variable-length matrix row sub-ranges using start and stop indices
1 view (last 30 days)
Show older comments
% Here's an interesting problem. I've tried to make it generic so your answers
% (hopefully) will be more widely useful.
%
% Context:
% - I have a latency sensitive program.
% - I need to do some basic sub-referencing, such that I can
% - build up values in a matrix based on start and stop indices for each row.
% - I also want to be able to zero out values based on a non-index criteria.
% Assume I have:
sz = 11; % length of rows
ind_ini = [1 1 1 5 1 1]'; % starting indices
ind_end = [11 10 1 6 3 2]'; % stopping indices
vals = [1111 2222 3333 4444 5555 6666]'; % values to span index range
pts = linspace(0,1,sz); % ref values for add'l criteria
rand_max = [1 1 .3 .2 .1 .9]'; % max values for add'l criteria
% method 1
ind_logic = bsxfun(@ge,1:sz,ind_ini) & ...
bsxfun(@le,1:sz,ind_end) & ...
bsxfun(@le,pts,rand_max);
m = bsxfun(@times,ind_logic,vals); % matrix containing value spans
% method 2
n = zeros(length(vals),sz); % matrix containing value spans
for i = 1:length(vals)
n(i,ind_ini(i):ind_end(i)) = vals(i);
n(i,pts > rand_max(i)) = 0;
end
ind_logic = n > 0;
all(all(m == n))
m
% m =
%
% Columns 1 through 6
%
% 1111 1111 1111 1111 1111 1111
% 2222 2222 2222 2222 2222 2222
% 3333 0 0 0 0 0
% 0 0 0 0 0 0
% 5555 5555 0 0 0 0
% 6666 6666 0 0 0 0
%
% Columns 7 through 11
%
% 1111 1111 1111 1111 1111
% 2222 2222 2222 2222 0
% 0 0 0 0 0
% 0 0 0 0 0
% 0 0 0 0 0
% 0 0 0 0 0
% Both of these methods provide the desired output, but they seem
% computationally inefficient. The loop is inefficient for obvious reasons, and
% the bsxfun approach seems like a lot of logical map generation for something
% as "simple" as variable sub-ranges.
% What I would prefer is to have some non-iterative in-line method for
% referencing the sub-ranges of the rows in order to set them to the respective
% values. Something like:
m(ind_ini:ind_end) = vals
% where ind_ini and ind_end are the same vectors of indices. Since the lengths
% of these index-ranges are not consistent, "cells" came to mind. Something
% like:
subs = cellfun(@(x,y) x:y,num2cell(ind_ini),num2cell(ind_end),...
'UniformOutput',0)
% subs =
%
% [1x11 double]
% [1x10 double]
% [ 1]
% [1x2 double]
% [1x3 double]
% [1x2 double]
% but then I have the same problem when I try to refernce "m(subs) = vals"
% DOES ANYONE HAVE ANY CLEVER IDEAS?
0 Comments
Accepted Answer
Andrei Bobrov
on 16 Jun 2011
Z = bsxfun(@times,vals,bsxfun(@le,pts,rand_max ));
mcell= arrayfun(@(j1)Z(j1,ind_ini(j1):ind_end(j1)),(1:length(ind_ini))','un',0);
EDIT
v = 1:sz;
m = cell2mat(arrayfun(@(i1)(vals(i1)*(+(ind_ini(i1)<=v&ind_end(i1)>=v&pts<=rand_max(i1))))',1:length(ind_ini),'un',0))'
about speed ... try the following:
v=1:sz;for i1 = length(ind_ini):-1:1, m(i1,:) = vals(i1)*(+(ind_ini(i1)<=v&ind_end(i1)>=v&pts<=rand_max(i1))); end;
my research
tic;v=1:sz;ind_logic = bsxfun(@ge,v,ind_ini) &bsxfun(@le,v,ind_end) & bsxfun(@le,pts,rand_max);m = bsxfun(@times,ind_logic,vals);toc
Elapsed time is 0.000668 seconds.
>> tic;v = 1:sz;m = cell2mat(arrayfun(@(i1)(vals(i1)*(+(ind_ini(i1)<=v&ind_end(i1)>=v&pts<=rand_max(i1))))',1:length(ind_ini),'un',0))';toc
Elapsed time is 0.001297 seconds.
>> tic,v=1:sz;for i1 = length(ind_ini):-1:1, m(i1,:) = vals(i1)*(+(ind_ini(i1)<=v&ind_end(i1)>=v&pts<=rand_max(i1))); end; toc
Elapsed time is 0.000113 seconds.
4 Comments
Andrei Bobrov
on 19 Jun 2011
about speed
<http://www.mathworks.com/matlabcentral/answers/7039-how-to-multiply-a-vector-with-each-column-of-a-matrix-most-efficiently>
More Answers (1)
See Also
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!