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

Appending to an array of repeated elements in matlab

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

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 的情况下追加组合数组?或者,如果也不是,是否有另一种更简单的方法来解决这个问题?

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

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

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


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

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

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 仅设计用于接收 integer 键。如果你有 浮点数 值,你仍然可以使用 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,依此类推。