navr91
navr91

Reputation: 236

Accessing Ranges of Data in Vectorized Way MATLAB

I have a column vector of data in variable vdata and a list of indeces idx. I want to access vdata at the indeces x before and x after each index in idx. One way I would do it in a for loop is:

x = 10;
accessed_data = [];
for (ii = 1:length(idx))
    accessed_data = vdata(idx-x:idx+x);
end

Is there a way to do this in a vectorized function? I found a solution to a very similar question here: Addressing multiple ranges via indices in a vector but I don't understand the code :(.

Upvotes: 1

Views: 72

Answers (3)

Luis Mendo
Luis Mendo

Reputation: 112659

This gives the solution in a matrix, with one row for each value in idx. It assumes that all values in idx are greater than or equal to x, and less than or equal to length(vdata)-x.

% Data
x = 10;
idx = [12 20 15];
vdata = 1:100;

ind = repmat(-x:x,length(idx),1) + repmat(idx(:),1,2*x+1);
vdata(ind)

Upvotes: 0

horchler
horchler

Reputation: 18484

One scheme that uses direct indexing instead of a for loop:

xx = (-x:x).';                            % Range of indices
idxx = bsxfun(@plus,xx(:,ones(1,numel(idx))),idx(:).'); % Build array
idxx = idxx(:);                           % Columnize to interleave columns
idxx = idxx(idxx>=1&idxx<=length(vdata)); % Make sure the idx+/-x is valid index
accessed_data = vdata(idxx);              % Indices of data

The second line can be replaced with a form of the first line from @Shai's answer. This scheme checks that all of the resultant indices are valid. Because some might have to be removed, you could end up with a ragged array. One way to solve this is to use cell arrays, but here I just make idxx a vector, and thus accessed_data is as well.

Upvotes: 2

Shai
Shai

Reputation: 114786

Assuming min(idx)-x>0 and max(idx)+x<=numel(vdata) then you can simply do

 iidx = bsxfun(@plus, idx(:), -x:x); % create all indices
 accessed_data = vdata( iidx );

Upvotes: 2

Related Questions