Concatenate subfields from Matlab structure into one data array

Don’t you just hate when you have an MxN struct array in Matlab, where each element contains some PxK data field, and you just really want to have all that data in a single PxKxMxN array? OK, maybe this doesn’t happen to you very frequently, but it has happened to me. In fact, it has happened so often that I decided to write a (very simple) general solution to this problem.

Let me motivate the problem with an example. I was dealing with Granger causality spectra that are stored in FieldTrip structures as follows:

>> allconns(1)

ans =

  struct with fields:

            label: {7×1 cell}
           dimord: 'chan_chan_freq'
    grangerspctrm: [7×7×101 double]
             freq: [1×101 double]
              cfg: [1×1 struct]

and I had one of these structures per participant, per condition of my experiment, and per time-direction (forward or reverse; details don’t really matter here). The structures were all tucked into one structure variable allconns such that

>> size(allconns)

ans =

    36     7     2

To get out the data into one big 6-dimensional array, I first concatenated along the fourth dimension:

catdat = cat(4, allconns.grangerspctrm);

which unfortunately flattens all those 36x7x2 dimensions such that

>> size(catdat)

ans =

     7     7   101   504

However, it’s easy to just get those back by one final reshape:

catdat = reshape(catdat, [7 7 101 36 7 2]);

The above works because Matlab stores data in column-major order.

It’s very straightforward to embed this into a simple function (also available on GitHub):

function x = structcat(y, param)
% STRUCTCAT takes a structure y of arbitrary dimensionality Mx...xN, each
% element of which contains a field named of dimensionality
% Px...xK, and returns the data in those fields concatenated into a
% Px...XKxMx...N array.
%
% Author: Eelke Spaak, 2018.

siz1 = size(y);
siz2 = size(y(1).(param));

x = cat(numel(siz2)+1, y.(param));
x = reshape(x, [siz2 siz1]);

end

I hope this is useful to someone who’s encountered the same!

Leave a Reply

Your email address will not be published. Required fields are marked *