【问题标题】:Sum each element across a structure containing oddly sized arrays [MATLAB]对包含奇数大小数组的结构中的每个元素求和 [MATLAB]
【发布时间】:2014-07-21 02:13:53
【问题描述】:

我花了一些时间研究这个,但很可能错过了一些简单的东西。我有中级 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 无论如何都不起作用。

所以现在我知识有限,正在寻求帮助,有人可以解决这个问题吗?

干杯, 亚历克斯

【问题讨论】:

    标签: arrays matlab data-structures cells


    【解决方案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
    

    代码 cmets 中介绍了基本步骤。 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?

    【讨论】:

    • Edit* 努力适应我的回复,我将回复我的原件
    【解决方案2】:

    @伊冯

    感谢您的回复,代码看起来很棒,我已经花时间浏览它。我将把它存档,因为它有一些我不知道的快捷方式。不幸的是,它似乎并没有解决我的问题,可能是由于我缺乏经验并且无法操纵您的慷慨捐助以使其对我有用。除了卑躬屈膝,我的结果如下

    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 乘以最后一个维度。例如,比较这些字段,顶部是原始的,底部是来自您的输出:

    cousinMagCorr: [4x4x5 double]
    

    对比

    cousinMagCorr: [1x4x150 double]
    

    注意最终尺寸乘以 30?我在尝试遍历字段并将单元格转换为矩阵时遇到了这个问题;他们适用于 2d,但不是更高的配置,这就像您的输出一样,其中最后一个维度乘以 n 次试验。

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

    再次感谢, 亚历克斯

    【讨论】:

    • 如果还是不行,能否给我举个autoCorrReal的例子?
    • 我做了一个快速修复。我对转换单元格数组的代码有误。试试新代码:)
    • 惊人的!你真的超越了,我非常感激。这在周末困扰着我,对我的实验至关重要,而且对时间非常敏感,因此我伸出手而不是学习。非常感谢您的意见。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-02
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    相关资源
    最近更新 更多