Romain
Romain

Reputation: 340

Matlab last dimension access on ndimensions matrix

I have as entry a matrix which can have an several number of dimensions : n × m or n × m × p or n × m × p × q or ...

What I want to do is to access to the last dimension, something like:

data = input(:,:,1)

The problem is that the number of : can change.

Upvotes: 13

Views: 2836

Answers (6)

Eddy Xiao
Eddy Xiao

Reputation: 313

Just in case GNU Octave readers reach here.

@Rody Oldenhuis's answer can be written as an one-liner in Octave:

> data = reshape(1:8, 2, 2, 2);
> data({':'}(ones(1,ndims(data)-1)){:}, 1)
ans =

   1   3
   2   4

Here:

{':'}(ones(1,ndims(data)-1)){:}

means:

tmp = {':'};
tmp = tmp(ones(1,ndims(data)-1));
tmp{:}

Of couse, repmat({':'},1,ndims(data)-1){:} works also.

Upvotes: 0

Luis Mendo
Luis Mendo

Reputation: 112729

Nice question!

Another possibility is to use linear indexing in blocks and then reshape:

x = rand(2,3,4,5); % example data
n = 2; % we want x(:,:,...,:,n)

siz = size(x);
b = numel(x)/siz(end); % block size
result = reshape(x(b*(n-1)+1:b*n),siz(1:end-1));

This seems to be the fastest approach in my computer (but do try yourself; that may depend on Matlab version and system)

Upvotes: 2

Rody Oldenhuis
Rody Oldenhuis

Reputation: 38032

You should make use of the fact that indices into an array can be strings containing ':':

>> data = rand(2, 2, 2, 5);
>> otherdims = repmat({':'},1,ndims(data)-1);
>> data(otherdims{:}, 1)
ans(:,:,1) =
    7.819319665880019e-001    2.940663337586285e-001
    1.006063223624215e-001    2.373730197055792e-001
ans(:,:,2) =
    5.308722570279284e-001    4.053154198805913e-001
    9.149873133941222e-002    1.048462471157565e-001

See the documentation on subsref for details.

Upvotes: 14

Mohsen Nosratinia
Mohsen Nosratinia

Reputation: 9864

You can use shiftdim to bring the last dimension to the first and index that one and reshape it back

x = rand(2,3,4,5,6);

sz = size(x);
A = shiftdim(x, numel(sz)-1);
B = reshape(A(1,:), sz(1:end-1));

and

>> isequal(B, x(:,:,:,:,1))
ans =
     1

or alternatively you can use subsref to index it:

B = subsref(x, substruct('()', [num2cell(repmat(':', 1, ndims(x)-1)) 1]))

Upvotes: 2

Dan
Dan

Reputation: 45752

I think this does it:

a = rand(2,2,2,3)

s = size(a)
r = reshape(a, [], s(end))
reshape(r(:,1), s(1:end-1)) %// reshape(r(:,2), s(1:end-1)) gives you a(:,:,:,...,2) etc...

I benchmarked against Dennis's (correct) answer and it gives the same result but doesn't need eval which is always worth avoiding if possible.

Upvotes: 1

Dennis Jaheruddin
Dennis Jaheruddin

Reputation: 21563

It is a bit of a hack, but here is how you can do it:

data = rand(2,2,3);

eval(['data(' repmat(':,',1,ndims(data)-1) '1)'])

This will give (depending on the randon numbers):

ans =

      0.19255      0.56236
      0.62524      0.90487

Upvotes: 5

Related Questions