define variable-length matrix row sub-ranges using start and stop indices
1 Ansicht (letzte 30 Tage)
Ältere Kommentare anzeigen
% 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 Kommentare
Akzeptierte Antwort
Andrei Bobrov
am 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 Kommentare
Andrei Bobrov
am 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>
Weitere Antworten (1)
Siehe auch
Kategorien
Mehr zu Matrix Indexing finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!