对包含奇数大小数组的结构中的每个元素求和[MATLAB]

时间:2014-07-21 02:13:54

标签: arrays matlab data-structures cells

我花了一些时间研究这个,但可能会遗漏一些简单的事情。我有中级Matlab知识。

我有一个从实验中保存的数据结构;

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

每个子字段('数组'?术语可能不正确,我很抱歉)的大小不同。我需要平均30个条目(试验)以保持上述形状,但每个区域内每个细胞的值在30个试验中取平均值。我也需要方差(我试图计算Z分数,看看其他试验是否与这个人群有显着差异)。

首先,我尝试在for循环中执行此操作,然后获取字段名,然后为每个字段打入并尝试在30个试验中添加每个元素的值,尽管此策略不起作用对于尺寸不同的字段(例如,我需要根据当前字段的尺寸可变地为循环创建不同尺寸)。

然后我尝试将数据结构转换为有效的单元格数组;

cell_in = struct2cell(s_params_in)

cell_in = 10x1x30  607440  cell 

...然后我尝试了一些我在搜索中发现的使用cellfun的东西,但老实说我并不完全确定它是如何工作的。我不得不添加UniformOutput来处理不等大小的字段。

cellfun( @(cell_in) sum(cell_in(:)), cell_in,'UniformOutput',false)

将每个'字段中的所有值相加。对于所有30个试验,(第一维),在其中的元素之间折叠。例如

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]

我尝试过如何调用cell_in(:)部分,但无法获得我正在寻找的结果,即在整个维度上求解的数组,同时保留其他维度。

我还尝试将其转换为矩阵,然后我可以使用类似

的东西
sum([data(:)])

然后重新整形以恢复原始尺寸,虽然这似乎也很困难,我可能不得不每个字段都这样做并手动输入尺寸。由于尺寸不一致,cell2mat无论如何都无法工作。

所以,现在我的知识极限并且正在寻求帮助,任何人都可以解决这个问题吗?

干杯, 亚历

2 个答案:

答案 0 :(得分:1)

工作代码。

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

代码注释中解决了基本步骤。 TT是对一种特定类型的实验数据的30次试验。假设您处于字段pixelLPStats的迭代中。每个试验都有一个由此名称指定的矩阵,它是一个5x2双数组。因此,TT将是一个5x2x30阵列。你可以用它做你想做的事。然后让循环将您带到下一个字段。


我想这次我得到了正确的答案?

>> ( S(1).f2 + S(2).f2 )/2 == T.f2

ans(:,:,1) =

     1     1     1     1
     1     1     1     1
     1     1     1     1


ans(:,:,2) =

     1     1     1     1
     1     1     1     1
     1     1     1     1

>> 

将N维矩阵的单元格数组转换为一个(N + 1)维度矩阵的另一种方法 - How to average over a cell-array of arrays?

答案 1 :(得分:0)

@Yvon

感谢您的回复,代码看起来很棒,我花了很多时间来完成它。我将保留这一个,因为它有一些我不知道的快捷方式。不幸的是,似乎没有解决我的问题,可能是由于我缺乏经验和无法操纵你的慷慨捐助,使它适合我。不管怎样,我的结果如下

pixelStats: [1x6x30 double]
  pixelLPStats: [1x2x30 double]
  autoCorrReal: [1x9x150 double]
   autoCorrMag: [4-D double]
      magMeans: [1x1x30 double]
 cousinMagCorr: [1x4x150 double]
 parentMagCorr: [1x4x120 double]
cousinRealCorr: [1x8x150 double]
parentRealCorr: [1x8x120 double]
   varianceHPR: [1x1x30 double]

首先,当我逐步执行代码时,均值/方差部分似乎不起作用,它只是使用mxmx30数组填充该字段,而不是每个元素的mxnx1数组'是的意思。还有关于上述输出的尺寸。请注意,表示30个试验的维度已添加到每个字段中,有些似乎与最后一个维度相乘30。例如,comapre这些字段,顶部是原始字段,底部是输出:

cousinMagCorr: [4x4x5 double]

VS。

cousinMagCorr: [1x4x150 double]

注意最终尺寸乘以30?我遇到了这个问题,试图遍历字段并将单元格转换为矩阵;他们工作了2d,但没有更高的配置,就像你的输出一样,最后一个维度乘以n次试验。

很可能我不清楚;我希望得到类似结构中的第一个条目,其中每个字段中的所有值对应于30个试验中该值的平均值。我对每个单独的值感兴趣,而不是在字段中跨维度折叠。

再次感谢, 亚历