0
votes

I am working with high-dimensional arrays with inconsistent dimensionalities, but all contain 6+ dimensions, and the last 3 represent 3D space in XYZ. For each x,y,z index, I wish to calculate the mean value for that index, collapsing across all other dimensions. I am currently using vectors to gather these values within nested for-loops, and averaging them, as in the following set of code snippets ('betas' is the multidimensional array in question):

First, obtain dimensions of betas

betasdim=size(betas);

Calculate the size of the 3D space, and the number of dimensions I need to collapse over. The last 3 dimensions of betasdim are XYZ:

voxdim=betasdim(length(betasdim)-2:length(betasdim));

Everything else are the dimensions to collapse over

otherdims=betasdim(1:length(betasdim)-3);

How many dimensions are being collapsed over?

numdims=length(otherdims);

Ceate a vector of colons to collapse over all dimensions other than XYZ:

dimwildcard=repmat({':'}, 1, numdims);

Initialize the mean matrix

meanbetas=repmat([NaN],voxdim);

And now the likely inefficient for-loop solution:

for x=1:voxdim(1)
 for y=1:voxdim(2)
   for z=1:voxdim(3)
      voxbetas=betas(dimwildcard{:},x,y,z);%get all beta values for this xyz 
      voxbetas=reshape(voxbetas,1, numel(voxbetas));%reshape to vector
       meanbetas(x,y,z)=nanmean(voxbetas); %average the vector and store in new array
    end
   end
 end

bearing in mind that I need a single value from nanmean() at each index, is there a faster solution other than to iterate through each value of x,y,z?

1

1 Answers

2
votes

If I understood correctly, what you want is squeeze(mean(mean...(mean(betas))...)). You can achieve it this way:

betas = randn(2,3,4,5,6,7); %// example data
meanbetas = betas; %// intialization
for n = 1:ndims(betas)-3
     meanbetas = mean(meanbetas); %// average along first non-singleton dimension
end
meanbetas = squeeze(meanbetas); %// remove singleton dimensions

Alternatively, you could reshape so that all dimensions except the last three collapse into a single (first) dimension, and average only once along that first dimension:

betas = randn(2,3,4,5,6,7); %// example data
N = ndims(betas); %// number of dimensions
meanbetas = squeeze(mean(reshape(betas, ...
    [], size(betas,N-2), size(betas,N-1), size(betas,N)), 1));