Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Acessing multiple structure fields in matlab without looping through it

I Have a 8x18 structure with each cel containing a column vector of occurrences of a single event. I want to obtain data from some of these fields concatenated in a single array, without having to loop through it. I can't seem to find a way to vertically concatenate the fields I am interested in in a single array.

As an example I create the following structure with between 1 and 5 occurrences per cell:

s(62).vector(8,18).heading.occurrences=[1;2;3];
for i=1:62
    for j=1:8
        for k=1:18
            y=ceil(rand(1)*5);
            s(i).vector(j,k).heading.occurrences=rand(y,1);
        end
    end
end

Now if want to obtain all occurrences in several cells while keeping i constant at for instant i=1 the following works:

ss=s(1).vector([1 26 45]);                     
h=[ss.heading];            
cell2mat({h.occurrences}')

Now I would want to do the same for s, for instance s([1 2 3]).vector([1 26 45]), how would that work? I have tried xx=s([1 2 3]), yy=xx.vector([1 26 45]) but this however yields the error:

Expected one output from a curly brace or dot indexing expression, but there were 3 results.

Is this also possible with a vector operation?

like image 345
Jasper Avatar asked Jun 20 '17 09:06

Jasper


People also ask

How Do We iterate through multiple structures in Matlab?

Direct link to this answer You have all the structures in gstr. You can access any structure using eval(gstr(i)). You can fields using fields(eval(gstr(i)).

How do you access a field in a structure in Matlab?

Description. value = getfield( S , field ) returns the value in the specified field of the structure S . For example, if S.a = 1 , then getfield(S,'a') returns 1 . As an alternative to getfield , use dot notation, value = S.

How do I stop an infinite loop from running Matlab?

To stop execution of whatever is currently running, press Ctrl+C or Ctrl+Break.


2 Answers

Here's a vectorized solution that accommodates using index vectors for s and the field vector:

sIndex = [1 2 3];    % Indices for s
vIndex = [1 26 45];  % Indices for 'vector' field

v = reshape(cat(3, s(sIndex).vector), 144, []);
h = [v(vIndex, :).heading];
out = vertcat(h.occurrences);

It uses cat to concatenate all the vector fields into an 8-by-18-by-numel(sIndex) matrix, reshapes that into a 144-by-numel(sIndex) matrix, then indexes the rows specified by vIndex and collects their heading and occurrences fields, using vertcat instead of cell2mat.

like image 143
gnovice Avatar answered Oct 20 '22 01:10

gnovice


It's difficult to vectorize the entire operation, but this should work.

% get vector field and store in cell array
s_new = { s(1:3).vector };

% now extract heading field, this is a cell-of-cells
s_new_heading = cellfun(@(x) { x.heading }', s_new, 'UniformOutput', false);

occurences = {};
for iCell = 1:length(s_new_heading)
    % use current cell
    cellHere = s_new_heading{iCell};

    % retain indices of interest, these could be different for each cell
    cellHere = cellHere([ 1 26 45 ]);

    % extract occurrences
    h = cellfun(@(x) x.occurrences, cellHere, 'UniformOutput', false);
    h_mat = cell2mat(h);

    % save them in cell array 
    occurences = cat(1, occurences, h_mat);
end
like image 22
kedarps Avatar answered Oct 20 '22 00:10

kedarps