2013-11-15 1 views
0

Я работаю с многомерными массивами с несогласованными размерами, но все они содержат 6 + размеры, а последние 3 представляют собой 3D-пространство в XYZ. Для каждого x, y, z index, я хочу рассчитать среднее значение для этого индекса, сворачиваясь по всем другим измерениям. В настоящее время я использую векторы для сбора этих значений внутри вложенных for-loops и их усреднения, как в следующем наборе фрагментов кода ('betas' - многомерный массив, о котором идет речь):Matlab: оптимальный способ для средних многомерных матричных ячеек

Сначала получите размеры бета

betasdim=size(betas); 

Рассчитайте размер 3D-пространства и количество измерений, которые необходимо свернуть. Последние 3 Размеры betasdim являются XYZ:

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

Все остальное имеют размеры, чтобы свернуть над

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

Сколько размеры разваливались над?

numdims=length(otherdims); 

Цеит вектор двоеточия разрушаться над всеми другими, чем XYZ размеров:

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

Инициализировать средней матрица

meanbetas=repmat([NaN],voxdim); 

А теперь, вероятно, неэффективное решение для цикла:

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 

, имея в виду, что для каждого индекса требуется одно значение из nanmean(), существует ли более быстрое решение, кроме того, чтобы перебирать каждое значение x, y, z?

ответ

2

Если я правильно понял, что вы хотите, то squeeze(mean(mean...(mean(betas))...)). Вы можете достичь его таким образом:

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 

В качестве альтернативы, вы можете изменить так, что все размеры, кроме трех последних коллапсу в один (первый) измерения, и в среднем только один раз по этому первому измерению:

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));