4

我有一组数据,其中我以 3 个读数为一组记录了值(以便能够获得 SEM 的一般概念)。我将它们记录在一个如下所示的列表中,我试图将其分解为每组 3 个点的平均值:

原始表

我想基本上将每 3 行折叠成一行,其中给出了该集合的平均数据值。本质上,它看起来如下:

期望的结果

这是我基本上知道如何在 Excel 中做的事情(即使用数据透视表),但我不确定如何在 MATLAB 中做同样的事情。我尝试过使用accumarray,但很难知道如何从本质上合并多个条件。我需要创建一个subs数组,其编号对应于每组唯一的 3 个数据点。通过蛮力,我可以创建一个数组,例如:

subs = [1 1 1; 2 2 2; 3 3 3; 4 4 4; ...]'

使用一些循环并将其作为我的 subs 数组,但由于它与数据本身无关,并且整个过程中可能会出现奇怪的问题(即每组超过 3 个数据点,或丢失数据等)。我知道必须有某种方法可以为这样的事情进行这种 Pivot-table-esque 分组,但需要一些帮助才能使其起步。谢谢。

这是文本形式的输入数据:

Subject  Flow   On/Off   Values
1        10     1        2.20
1        10     1        2.50
1        10     1        2.60
1        20     1        5.50
1        20     1        6.10
1        20     1        5.90
1        30     1        10.10
1        30     1        10.50
1        30     1        10.50
1        10     0        1.90
1        10     0        2.20
1        10     0        2.30
1        20     0        5.20
1        20     0        5.80
1        20     0        5.60
1        30     0        9.80
1        30     0        10.20
1        30     0        10.20
2        10     1        5.70
2        10     1        6.00
2        10     1        6.10
2        20     1        9.00
2        20     1        9.60
2        20     1        9.40
2        30     1        13.60
2        30     1        14.00
2        30     1        14.00
2        10     0        5.40
2        10     0        5.70
2        10     0        5.80
2        20     0        8.70
2        20     0        9.30
2        20     0        9.10
2        30     0        13.30
2        30     0        13.70
2        30     0        13.70
4

4 回答 4

4

您可以使用uniqueand accumarraylike 来维护数据行的顺序:

[newData, ~, subs] = unique(data(:, 1:3), 'rows', 'stable');
newData(:, 4) = accumarray(subs, data(:, 4), [], @mean);

newData =

    1.0000   10.0000    1.0000    2.4333
    1.0000   20.0000    1.0000    5.8333
    1.0000   30.0000    1.0000   10.3667
    1.0000   10.0000         0    2.1333
    1.0000   20.0000         0    5.5333
    1.0000   30.0000         0   10.0667
    2.0000   10.0000    1.0000    5.9333
    2.0000   20.0000    1.0000    9.3333
    2.0000   30.0000    1.0000   13.8667
    2.0000   10.0000         0    5.6333
    2.0000   20.0000         0    9.0333
    2.0000   30.0000         0   13.5667
于 2017-05-16T21:44:15.247 回答
3

我假设

  • 您希望根据前三列的唯一值进行平均(不是三行组,尽管在您的示例中这两个条件一致);
  • 顺序由第 1 列、第 3 列、第 2 列确定。

然后,将您的数据表示为x

[~, ~, subs] = unique(x(:, [1 3 2]), 'rows', 'sorted');
result = accumarray(subs, x(:,end), [], @mean);

result =
    2.1333
    5.5333
   10.0667
    2.4333
    5.8333
   10.3667
    5.6333
    9.0333
   13.5667
    5.9333
    9.3333
   13.8667

如您所见,我正在使用 and 选项的第三unique'rows'输出'sorted'subs这将根据数据的前三列按所需顺序创建分组向量。然后,将其传递给accumarray计算均值。

于 2017-05-16T21:36:13.500 回答
0

您还应该尝试查看findgroupssplitapply参考页面。在这里使用它们的最简单方法可能是将数据放在表中:

 >> T = array2table(data, 'VariableNames', { 'Subject', 'Flow', 'On_Off', 'Values'});
 >> [gid,Tgrp] = findgroups(T(:,1:3));
 >> Tgrp.MeanValue = splitapply(@mean, T(:,4), gid)
 Tgrp =
   12×4 table
     Subject    Flow    On_Off    MeanValue
     _______    ____    ______    _________
     1          10      0         2.1333   
     1          10      1         2.4333   
     1          20      0         5.5333   
     1          20      1         5.8333   
     1          30      0         10.067   
     1          30      1         10.367   
     2          10      0         5.6333   
     2          10      1         5.9333   
     2          20      0         9.0333   
     2          20      1         9.3333   
     2          30      0         13.567   
     2          30      1         13.867   
于 2017-05-17T14:26:40.320 回答
0

accumarray确实是要走的路。首先,您需要为每组值分配一个索引unique

[unique_subjects, ~, ind_subjects] = unique(vect_subjects);
[unique_flows, ~, ind_flows] = unique(vect_flows);
[unique_on_off, ~, ind_on_off] = unique(vect_on_off);

所以基本上,你现在得到ind_subjects,ind_flows和,和ind_on_off中的值。[1..2][1..3][1..2]

[3x2x2]现在,您可以计算数组中的平均值(在您的示例中):

mean_values = accumarray([ind_flows, ind_on_off, ind_subjects], vect_values, [], @mean);
mean_values = mean_values(:);

注意:订单是根据您的示例设置的。

然后您可以构建摘要:

[ind1, ind2, ind3] = ndgrid(1:numel(unique_flows), 1:numel(unique_on_off), 1:numel(unique_subjects));
flows_summary = unique_flows(ind1(:));
on_off_summary = unique_on_off(ind2(:));
subjects_summary = unique_subjects(ind3(:));

注意:也适用于非数值。

于 2017-05-16T21:54:40.477 回答