在matlab中附加到重复元素的数组

时间:2015-01-20 03:55:20

标签: arrays matlab append

数据变量是3x9阵列,其中第一行是电压,第二行是计数,第三行是错误。我想平均每个电压的计数/误差,以便处理后的数组类似于

combined = [1,2,3;.99,.1.2,1.3;.2,.3,.5]

到目前为止,我的尝试是:

data = [1,1,1,2,2,2,3,3,3;...
       .98,.99,.98,1.1,1.2,1.2,1.3,1.3,1.4;...
       .3,.2,.2,.3,.3,.4,.5,.4,.5];
volt = data(1,:);
v_uniq=unique(volt);%Array of unique voltage values

for k=1:length(v_uniq)
    volt_i=find(volt==v_uniq(k));%Indices for set of repeating values
    combined_m(k)=mean(data(2,volt_i(1):volt_i(end)).')';%averaged means
    combined_e(k)=mean(data(3,volt_i(1):volt_i(end)).')';%averaged error
    combined(k) = [combined_m(k);combined_e(k)];
    %combined(k)=combined(k);
end

挑战性的部分是在每次迭代后附加组合数组,因为v_uniq本身就是一个数组,并且在尝试迭代时会导致问题。

有没有办法在不必索引v_uniq的情况下附加组合数组?或者,如果没有,还有另一种更简单的方法来解决这个问题吗?

1 个答案:

答案 0 :(得分:4)

如果您想让您的代码正常工作,请在上面对您的评论中使用Daniel的建议。只需将for循环代码的最后一行替换为:

combined(:,k) = [combined_m(k);combined_e(k)];

您想插入一列,显示每个唯一电压的组合计数和错误。


但是,我建议使用accumarray而不是for循环方法,并使用电压作为键,并使用矩阵的其他两行作为值。 accumarray的工作原理是您有两个数组:keysvalues。对于keys中存储的每个值,我们会在values中看到相应的数字,并将此数字放入由keys索引的bin中。一旦我们完成所有这些分箱,您就可以使用一个功能,将每个bin的所有这些条目组合在一起。默认情况下,accumarray使用sum,因此您只需将所有映射到每个bin的值相加。

但是,对于您的情况,您将使用mean作为应用于每个箱的函数,以查找每个唯一电压的平均误差和计数。像这样:

data = [1,1,1,2,2,2,3,3,3;...
.98,.99,.98,1.1,1.2,1.2,1.3,1.3,1.4;...
.3,.2,.2,.3,.3,.4,.5,.4,.5];

ave_counts = accumarray(data(1,:).', data(2,:).', [], @mean);
ave_error = accumarray(data(1,:).', data(3,:).', [], @mean);

combined = [ave_counts ave_error];

accumarray中,第一个参数是键,在我们的例子中是电压,values是计数或错误 - 基本上是那些需要组合的值。

ave_counts将包含每个唯一电压的平均计数,而ave_error将包含每个唯一电压的平均误差。然后我们可以将这些组合成一个2列矩阵,就像最后一行代码一样,创建combined,就像在代码中看到的那样。

由于您的电压已经逐渐增加,这意味着每个元素都与该电压完全对应。运行此功能后,我就可以获得ave_countsave_error

>> ave_counts

ave_counts =

    0.9833
    1.1667
    1.3333

>> ave_error

ave_error =

    0.2333
    0.3333
    0.4667

这表示对于voltage = 1,平均值和平均误差分别为0.98330.2333。您可以通过手动计算来验证这一点。前三个计数和错误是voltage = 1,如果我们计算平均误差和计数,我们得到:

(0.98+0.99+0.98) / 3 = 0.9833 <-- Average count for voltage = 1
(0.3+0.2+0.3) / 3 = 0.2333 <-- Average error for voltage = 1

同样适用于voltage = 2

(1.1+1.2+1.2) / 3 = 1.1667 <-- Average count for voltage = 2
(0.3+0.3+0.4) / 3 = 0.3333 <-- Average error for voltage = 2

最后为voltage = 3

(1.3+1.3+1.4) / 3 = 1.3333 <-- Average count for voltage = 3
(0.5+0.4+0.5) / 3 = 0.4667 <-- Average error for voltage = 3

我们手动计算的数量恰好是accumarray两个数量的输出。


买者

accumarray仅用于接受整数键。如果您有浮点值,您仍然可以使用accumarray,但您必须先进行一些预处理。我要做的是使用unique并专门使用第三个输出。第三个输出获取输入中的每个唯一值,并为其分配整数ID。任何相同的值都会被赋予相同的整数ID ,因此非常适合作为accumarray的输入。您还需要第一个输出来跟踪combined矩阵每行的平均电压。

因此,您将使用unique的第三个输出作为accumarray的输入。因此,做这样的事情:

[voltages,~,id] = unique(data(1,:));
ave_counts = accumarray(id, data(2,:).', [], @mean);
ave_error = accumarray(id, data(3,:).', [], @mean);
combined = [ave_counts ave_error];

在这种情况下,ave_countsave_error的每个元素都对应于voltages中存储的相同元素。因此,voltages(1)将对应于combined的第一行,voltages(2)将对应于combined的第二行,依此类推。

为了完整性,如果我们使用您的示例数据运行上述内容,这就是我们为voltagescombined获取的内容:

>> voltages

voltages =

     1     2     3

>> combined

combined =

    0.9833    0.2333
    1.1667    0.3333
    1.3333    0.4667

因此,voltage = 1给我们的平均点数为0.9833,平均误差为0.2333,依此类推。