Reputation: 236
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
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
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
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