Accessing multidimensional array with pairwise indices
16 次查看(过去 30 天)
显示 更早的评论
Hi everybody
Probably a stupid question but I can't get my head around it. Suppose A is a matrix with dimensions (20,20,1000). I have two vectors x and y with pairwise indices (lets say 5x1). Is there an easy & fast (vectorized) way to extract A(x(1),y(1),:), A(x(2),y(2),:) ... A(x(5),y(5),:)? The only solution I came up with would be sub2ind for the first two dimensions and repmat to expand a binary mask of the indices to the third dimension but that's probably not ideal performance- and memory-wise?
Any ideas?
Thanks in advance
2 个评论
James Tursa
2015-3-27
How do you want the extracted data (a bunch of 1000 element "vectors") arranged in the result variable?
回答(5 个)
Jon
2015-3-30
I think your for loop is only getting data off the top page of the array. When I run your code, B is [ni 1], but all the others results are [ni 2000]. You need to change the last index in A from '1' to ':'. You can also speed up your loop by initializing B before the loop.
B=zeros(numel(ix),size(A,3));
for i=1:numel(ix)
B(i,:)=A(ix(i),iy(i),:);
end
Also, I found the error in my snippet. The third line should be
ind2=bsxfun(@plus,ind,0:numel(A1):numel(A)-numel(A1));
With these changes, I get the following results for ni=1000.
forloop =0.074519
arrayfun=0.086363
bsxfun1 =0.040455
bsxfun2 =0.077431
0 个评论
dpb
2015-3-27
One solution; not sure if it's the fastest or not...returns an array of columns length as number of elements i the index arrays by the depth of the planes in the 3D array. Miniature example...
>> x=rand(3,3,2) % small data array
x(:,:,1) =
0.1524 0.9961 0.1067
0.8258 0.0782 0.9619
0.5383 0.4427 0.0046
x(:,:,2) =
0.7749 0.0844 0.8001
0.8173 0.3998 0.4314
0.8687 0.2599 0.9106
>> ix=[3 1];iy=[2 2]; % x,y coordinates to select
>> squeeze(cell2mat(arrayfun(@(i,j) x(i,j,:),ix,iy,'uniformoutput',0)))
ans =
0.4427 0.2599
0.9961 0.0844
>>
0 个评论
Jon
2015-3-27
I think sub2ind is the recommended approach in most cases. If you want to avoid repmat, you can do something like this.
>> A=rand(3,3,2)
A(:,:,1) =
0.35166 0.54972 0.7572
0.83083 0.91719 0.75373
0.58526 0.28584 0.38045
A(:,:,2) =
0.56782 0.5308 0.12991
0.075854 0.77917 0.56882
0.05395 0.93401 0.46939
>> ix=[3 1];iy=[2 2];
% Pull out the top page of the array for sizing
>> A1=A(:,:,1)
% get the indices of the rows/columns you want
>> ind=sub2ind(size(A1),ix,iy));
% extend the indices to cover all pages of the 3D array
>> ind2=bsxfun(@sum,ind',0:numel(A1):numel(A)-numel(A1));
% pull out the elements of the array you want
>> B=A(ind2)
B =
0.28584 0.93401
0.54972 0.5308
You can even put everything in one line if you want.
0 个评论
Roger Stafford
2015-3-28
If, as you have indicated, x and y are column vectors, do this:
B = reshape(A(bsxfun(@plus,(x+20*(y-1)).',(20*20)*(0:999).')),1,[]);
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Matrix Indexing 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!