Sum each element across a structure containing oddly sized arrays

1 view (last 30 days)
I've spent some time researching this, but am likely missing something simple. I have intermediate Matlab knowledge.
I have a structure of data saved from an experiment;
1x30 struct array with fields:
pixelStats: [118.6892 3.1370e+003 -0.1418 2.1195 -25.9308 259.3778]
pixelLPStats: [5x2 double]
autoCorrReal: [9x9x5 double]
autoCorrMag: [4-D double]
magMeans: [18x1 double]
cousinMagCorr: [4x4x5 double]
parentMagCorr: [4x4x4 double]
cousinRealCorr: [8x8x5 double]
parentRealCorr: [8x8x4 double]
varianceHPR: 21.5116
Where each sub-field ('arrays'? terminology is likely incorrect I'm sorry) is a different size. There are 30 entries (trials) that I need to average across so that the shape of the above is retained, but the values for each cell within each field are the averages for those values across the 30 trials. I also need the variance (I am trying to calculate Z scores to see if other trials are significantly different from this population).
First I tried to do this in a for loop, where I get the fieldnames, then for each field I break in and try to add the values for each element across the 30 trials, though this strategy doesn't work for fields with differently sized dimensions (e.g. I'd need to variably create differently sized for loops according to dimensions of current field).
Then I tried to convert the data structure to a cell array, which works;
cell_in = struct2cell(s_params_in)
cell_in = 10x1x30 607440 cell
...and then I tried something I found in my searching that uses cellfun, though to be honest I am not entirely sure of how it works. I had to add the UniformOutput to deal with unequal sized fields.
cellfun( @(cell_in) sum(cell_in(:)), cell_in,'UniformOutput',false)
This summed all values within each 'field' (first dimension), collapsing across elements within them, for all 30 trials. e.g.
ans(:,:,30) =
[3.4911e+003]
[ 10.9414]
[2.0854e+009]
[2.6877e+007]
[1.3612e+004]
[2.3328e+006]
[8.4917e+004]
[7.3826e+008]
[8.2038e+003]
[ 22.4030]
I tried playing around with how I called the cell_in(:) part, but could not get the result I was looking for i.e. an array summed across the dimension for trials, whilst retaining the other dimensionality.
I have also tried to convert that to a matrix and then I could use something like
sum([data(:)])
And play around with reshaping to get the original size back, though that also seems difficult and I'd probably have to do it per fields and manually input the dimensions. The cell2mat doesn't work anyhow on account of the inconsistent dimensions.
So now I'm at the limit of my knowledge and am reaching out for help, can anyone solve this?
Cheers, Alex
  1 Comment
Alex Coningham
Alex Coningham on 21 Jul 2014
I have received an answer from Yvon over on StackOverflow, click link for that question/answer, I will also post here for any googlers.
clear;clc
% create an example struct array
field1 = 'f1'; value1 = rand(1,10);
field2 = 'f2'; value2 = {rand(3,4,2), rand(3,4,2)};
field3 = 'f3'; value3 = {pi, pi.^2};
field4 = 'f4'; value4 = {magic(3), magic(3).^2};
S = struct(field1,value1,field2,value2,field3,value3,field4,value4);
clearvars field* value*
N = length(S);
T = struct();
U = T;
% enumerate over all fields (all should be numbers)
FN = fieldnames(S);
for ii=1:length(FN)
fn = FN{ii};
ss = {S.(fn)};
% convert cell array of N-dim matrices into one (N+1)-dim matrix
ssdim = ndims(ss{1});
TT = cell2mat( reshape(ss, [ones(1,ssdim),N]) );
% here you can do what you want
T.(fn) = mean(TT,ndims(TT));
U.(fn) = var(TT,0,ndims(TT));
end
clearvars ii ssdim ss fn TT
for ii=1:length(FN)
disp(FN{ii})
disp(T.(FN{ii}))
disp(U.(FN{ii}))
end
clearvars ii N
The basic steps are addressed in code comments. TT is 30 trials of one particular type of experimental data. Say you are in the iteration for field pixelLPStats. Each trial has a matrix assigned by this name, which is a 5x2 double array. So, TT will be a 5x2x30 array. You can do what you want with it. Then let the loop bring you to the next field.

Sign in to comment.

Answers (0)

Categories

Find more on Data Type Conversion in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!