在MATLAB中避免循环

时间:2016-03-26 19:41:36

标签: matlab vectorization

我在MATLAB中使用structure包含不同大小的数字数组,其行如下:

        SCD     |  HTD    |  EHD    | CSD
 T = [ 300*256  | 300*62  | 305*80  | 305*256 ...
       200*256  | 400*62  | 105*80  | 505*256 ...]

T包含许多行(size(T) = [1,965])。我想做的是,每列,计算组件在行上的平均值。我目前这样做:

Tmean = [] ;
for i = 1 : size(T,2)
     A = T(i).SCD ;
     Tmean(i).SCD = mean(table2array(A));      
end

我们需要在所有列上执行此操作。是否可以在不使用多个循环的情况下执行此操作?

T(1)和T(2)的输出如下所示:

  T(1)

  ans = 

    SCD: [305x256 table]
    HTD: [305x62 table]
    EHD: [305x80 table]
    DCD: [337x51 table]
    CSD: [305x256 table]
    CLD: [305x120 table]
    movieId: 89

   T(2)

   ans = 

    SCD: [263x256 table]
    HTD: [263x62 table]
    EHD: [263x80 table]
    DCD: [732x9 table]
    CSD: [263x256 table]
    CLD: [263x120 table]
    movieId: 93

我期望T(1)的Tmean_SCD看起来像[1 * 256]数组,而T(2)和T(1)都是相同的。因为第一个字段中的所有列都有256列,所以我们可以将它们放在一个包含256列和965行的数组中。

2 个答案:

答案 0 :(得分:2)

这是一个解决方案:

Tmean = struct();
fields = {'SCD', 'HTD', 'EHD', 'DCD', 'CSD', 'CLD'};
for i=1:numel(fields)
    Tmean.(fields{i}) = cell2mat(cellfun(@(t) mean(table2array(t)), ...
        {T.(fields{i})}, 'Uniform',false)');
end

为了测试它,我生成了这个样本结构数组,类似于你的数据形状(随机值):

T = struct();
for i=1:10  % your data is 965
    T(i).SCD = array2table(rand(randi([2 20]), 256));
    T(i).HTD = array2table(rand(randi([2 20]), 62));
    T(i).EHD = array2table(rand(randi([2 20]), 80));
    T(i).DCD = array2table(rand(randi([2 20]), 51));
    T(i).CSD = array2table(rand(randi([2 20]), 256));
    T(i).CLD = array2table(rand(randi([2 20]), 120));
    T(i).movieId = i;
end

实际结果:

>> Tmean
Tmean = 
    SCD: [10x256 double]
    HTD: [10x62 double]
    EHD: [10x80 double]
    DCD: [10x51 double]
    CSD: [10x256 double]
    CLD: [10x120 double]

一个标量结构,每个字段都是一个大小为956-by-(columnSize)的矩阵

答案 1 :(得分:0)

按照矢量化解决方案的要求,这里几乎是矢量化的解决方案。几乎因为我们仍然有一个arrayfun,它基本上是循环的包装器,但在我们的例子中,它只用于给我们输入数组的大小,所以没有或涉及到最少的计算。实现看起来像这样 -

accum_data = table2array(vertcat(T(:).SCD))
csums = cumsum(accum_data,1)
lens = arrayfun(@(n) size(T(n).SCD,1),1:size(T,2))
cut_idx = cumsum(lens)
sums = [csums(cut_idx(1),:) ; diff(csums(cut_idx,:),[],1)]
Tmean_SCDOut = bsxfun(@rdivide,sums,lens(:))

对于在其他字段上执行相同的平均操作,您需要同样迭代它们。