필터 지우기
필터 지우기

define variable-length matrix row sub-ranges using start and stop indices

조회 수: 2 (최근 30일)
% 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?

채택된 답변

Andrei Bobrov
Andrei Bobrov 2011년 6월 16일
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
Andrei Bobrov
Andrei Bobrov 2011년 6월 19일
about speed
<http://www.mathworks.com/matlabcentral/answers/7039-how-to-multiply-a-vector-with-each-column-of-a-matrix-most-efficiently>
Hannes Greim
Hannes Greim 2011년 6월 19일
Thanks. That works in the example I provided. It's certainly faster when the dimensions of the input arrays are small enough. It does not scale as well as bsxfun with larger arrays. Thanks for your input.

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Hannes Greim
Hannes Greim 2011년 6월 19일
Andrei's answer is faster when the input arrays are small. The example below shows that the bsxfun approach has a larger overhead, but scales much better for larger arrays.
edit func_1.m
% ------------------------------------------------------------------------------
function [m] = func_1(ind_ini,ind_end,vals,rand_max)
sz = 11; % length of rows
pts = linspace(0,1,sz); % ref values for add'l criteria
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);
end
% ------------------------------------------------------------------------------
% ------------------------------------------------------------------------------
edit func_2.m
% ------------------------------------------------------------------------------
function [m] = func_2(ind_ini,ind_end,vals,rand_max)
sz = 11; % length of rows
pts = linspace(0,1,sz); % ref values for add'l criteria
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
end
% ------------------------------------------------------------------------------
% ------------------------------------------------------------------------------
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
rand_max = [1 1 .3 .2 .1 .9]'; % max values for add'l criteria
tic;for i=1:1e5,m=func_1(ind_ini,ind_end,vals,rand_max);end;toc
% Elapsed time is 8.417756 seconds.
tic;for i=1:1e5,m=func_2(ind_ini,ind_end,vals,rand_max);end;toc
% Elapsed time is 6.002761 seconds.
mult = 3;
ind_ini = repmat(ind_ini,mult,1);
ind_end = repmat(ind_end,mult,1);
vals = repmat(vals,mult,1);
rand_max = repmat(rand_max,mult,1);
tic;for i=1:1e5,m=func_1(ind_ini,ind_end,vals,rand_max);end;toc
% Elapsed time is 8.182190 seconds.
tic;for i=1:1e5,m=func_2(ind_ini,ind_end,vals,rand_max);end;toc
% Elapsed time is 9.983013 seconds.
ind_ini = repmat(ind_ini,mult,1);
ind_end = repmat(ind_end,mult,1);
vals = repmat(vals,mult,1);
rand_max = repmat(rand_max,mult,1);
tic;for i=1:1e5,m=func_1(ind_ini,ind_end,vals,rand_max);end;toc
% Elapsed time is 8.710443 seconds.
tic;for i=1:1e5,m=func_2(ind_ini,ind_end,vals,rand_max);end;toc
% Elapsed time is 23.056634 seconds.

카테고리

Help CenterFile Exchange에서 Logical에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by