简体   繁体   English

Matlab中沿nd数组维度的平均bin

[英]average bins along a dimension of a nd array in matlab

To compute the mean of every bins along a dimension of a nd array in matlab, for example, average every 10 elements along dim 4 of a 4d array 例如,要计算沿Matlab中nd数组维度的每个bin的平均值,请沿4d数组的dim 4平均每10个元素的平均值

x = reshape(1:30*30*20*300,30,30,20,300);    
n = 10; 
m = size(x,4)/10;
y = nan(30,30,20,m);
for ii = 1 : m
    y(:,:,:,ii) = mean(x(:,:,:,(1:n)+(ii-1)*n),4);
end

It looks a bit silly. 看起来有点傻。 I think there must be better ways to average the bins? 我认为必须有更好的方法来平均垃圾箱?

Besides, is it possible to make the script applicable to general cases, namely, arbitray ndims of array and along an arbitray dim to average? 此外,是否可以使脚本适用于一般情况,即数组的arndray ndims以及沿arbitray变暗以求平均的情况?

For the second part of your question you can use this: 对于问题的第二部分,可以使用以下命令:

x = reshape(1:30*30*20*300,30,30,20,300);    
dim = 4;
n = 10; 
m = size(x,dim)/10;
y = nan(30,30,20,m);
idx1 = repmat({':'},1,ndims(x));
idx2 = repmat({':'},1,ndims(x));
for ii = 1 : m
    idx1{dim} = ii;
    idx2{dim} = (1:n)+(ii-1)*n;
    y(idx1{:}) = mean(x(idx2{:}),dim);
end

For the first part of the question here is an alternative using cumsum and diff , but it may not be better then the loop solution: 对于问题的第一部分,这里是使用cumsumdiff的替代方法,但它可能比循环解决方案更好:

function y = slicedmean(x,slice_size,dim)
    s = cumsum(x,dim);
    idx1 = repmat({':'},1,ndims(x));
    idx2 = repmat({':'},1,ndims(x));
    idx1{dim} = slice_size;
    idx2{dim} = slice_size:slice_size:size(x,dim);
    y = cat(dim,s(idx1{:}),diff(s(idx2{:}),[],dim))/slice_size;
end

Here is a generic solution, using the accumarray function. 这是使用accumarray函数的通用解决方案。 I haven't tested how fast it is. 我还没有测试它的速度。 There might be some room for improvement though. 虽然可能还有一些改进的空间。

Basically, accumarray groups the value in x following a matrix of customized index for your question 基本上,accumarray根据您的问题的自定义索引矩阵将x中的值分组

x = reshape(1:30*30*20*300,30,30,20,300); 
s = size(x);

% parameters for averaging
dimAv = 4; 
n = 10;

% get linear index
ix = (1:numel(x))';

% transform them to a matrix of index per dimension
% this is a customized version of ind2sub
pcum = [1 cumprod(s(1:end-1))];
sub = zeros(numel(ix),numel(s));
for i = numel(s):-1:1,
    ixtmp = rem(ix-1, pcum(i)) + 1;
    sub(:,i) = (ix - ixtmp)/pcum(i) + 1;
    ix = ixtmp;
end

% correct index for the given dimension
sub(:,dimAv) = floor((sub(:,dimAv)-1)/n)+1;

% run the accumarray to compute the average
sout = s;
sout(dimAv) = ceil(sout(dimAv)/n);
y = accumarray(sub,x(:), sout, @mean);

If you need a faster and memory efficient operation, you'll have to write your own mex function. 如果您需要更快的内存效率操作,则必须编写自己的mex函数。 It shouldn't be so difficult, I think ! 我想这应该没那么困难!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM