Selecting data from a dynamically named ND array
6 views (last 30 days)
Show older comments
I have a structure with fields of various dimensions - typically between 3 and 6. Each of the fields has one dimension that represents a sampling instance, but in some fields it is dimension 2, in others dimension 3 or 4. I need to extract a subset of the data from each of the fields by selecting samples along the relevant dimension, so if all of the fields were, say, 4D and the sampling dimension was 2 with ix as the selection, I could use:
flds = fieldnames(S.(inst))
for i = 1:numel(flds)
fld = flds{i};
S.(inst).(fld) = S.(inst).(fld)(:,ix,:,:);
clear fld
end; clear i
I can easily check the number of dimensions of the field and I can work out which dimension of the field I need to sample along, but I then end up with something like:
flds = fieldnames(S.(inst))
for i = 1:numel(flds)
fld = flds{i};
ndims = numel(size(S.(inst).(fld));
idir = find(size(S.(inst).(fld)) == Nsamples); % where Nsamples is the number of samples
if ndims == 3
if idir == 1
S.(inst).(fld) = S.(inst).(fld)(ix,:,:);
elseif idir == 2
S.(inst).(fld) = S.(inst).(fld)(:,ix,:);
else
S.(inst).(fld) = S.(inst).(fld)(:,:,ix;
end
elseif ndims == 4
if idir == 1
S.(inst).(fld) = S.(inst).(fld)(ix,:,:,:)
elseif idir == 2
% etc
% etc
end
clear fld
end; clear i
I wondered whether anyone could suggest a more elegant solution? I was thinking that it would be possible to dynamically generate the data selection (:,ix,:,:) as a text string and use it with eval, but I'm not sure that works with the dynamic naming of variables.
Any thoughts?
0 Comments
Accepted Answer
Stephen23
on 18 May 2017
Edited: Stephen23
on 6 Nov 2018
For a start you might like to read this (if you want to write better code, then it can help you):
And then to solve your problem you do not need to write lots of if-s or use eval, in fact you can do solve your quite simply by creating a cell array of indices and using that to generate a comma-separated list:
>> X = randi(9,1,2,3,4);
>> C = {':',':',2,':'};
>> X(C{:})
ans(:,:,1,1) =
1 1
ans(:,:,1,2) =
8 2
ans(:,:,1,3) =
3 8
ans(:,:,1,4) =
2 4
Another alternative is to call subsref directly. The function subsref is what MATLAB uses to index into variables, but you can also call it directly. All you need to do is create a suitable structure input, it is not that hard but you should play around with it to understand how it works. For example:
>> subsref(X,substruct('()',C))
ans(:,:,1,1) =
1 1
ans(:,:,1,2) =
8 2
ans(:,:,1,3) =
3 8
ans(:,:,1,4) =
2 4
Clearly it is pretty trivial to construct that cell array: something like this (untested):
C = repmat({':'},1,totdim);
C{ixdim} = ix;
2 Comments
More Answers (0)
See Also
Categories
Find more on Logical in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!