【问题标题】:Appending to an array of repeated elements in matlab在matlab中附加到重复元素的数组
【发布时间】:2015-01-21 05:13:53
【问题描述】:

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

【问题讨论】:

  • combined(:,k)= ... 可以解决您的问题。但我确信有一种更简洁的方式来做你想做的事。

标签: arrays matlab append


【解决方案1】:

如果您想让您的代码正常工作,可以使用 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 仅设计用于接收 整数 键。如果您有 浮点 值,您仍然可以使用 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,依此类推。

【讨论】:

    猜你喜欢
    • 2013-10-05
    • 1970-01-01
    • 2019-05-06
    • 2018-05-19
    • 1970-01-01
    • 2019-08-13
    • 1970-01-01
    • 2011-07-15
    • 2018-04-26
    相关资源
    最近更新 更多