计算 Octave 中行组的列的平均值

Posted

技术标签:

【中文标题】计算 Octave 中行组的列的平均值【英文标题】:Compute mean of columns for groups of rows in Octave 【发布时间】:2020-09-02 11:57:01 【问题描述】:

我有一个矩阵,例如:

1 2
3 4
4 5

我还有一个对行进行分组的规则,它被定义为一个组 ID 的向量,如下所示:

1
2
1

这意味着第一行和第三行属于同一个组(ID 1),第二行属于另一个组(ID 2)。所以,我想计算每个组的平均值。这是我的示例的结果:

2.5 3.5
3 4

更正式地说,有一个大小为(mn)的矩阵A,有若干组k 和一个大小为 (m, 1) 的向量 v,其值是从 1 到 k 的整数。结果是一个大小为 (k, n) 的矩阵 R,其中索引为 r 的每一行对应于r组的平均值。

这是我在 Octave 中使用 for-loop 的解决方案(可以满足我的需要):

R = zeros(k, n);
for r = 1:k
    R(r, :) = mean(A((v == r), :), 1);
end

我想知道它是否可以矢量化。因此,我需要用矢量化解决方案替换 for 循环,这将比迭代解决方案更有效。

这是我以矢量化方式解决问题的众多尝试之一(但不起作用):

R = mean(A((v == 1:k), :);

【问题讨论】:

【参考方案1】:

只要我们的数据是浮点数,你就可以自己手动求和然后除,使用accumdim。像这样:

octave:1> A = [1 2; 3 4; 4 5];
octave:2> subs = [1; 2; 1];
octave:3> accumdim (subs, A) ./ accumdim (subs, ones (rows (subs), 1))
ans =

   2.5000   3.5000
   3.0000   4.0000

【讨论】:

我不知道 accumdim。这似乎是我正在寻找的功能。谢谢你的指点。 不知道比this回答效率高吗?老实说,使用 accumdim 的解决方案可读性较差,所以我更喜欢它的唯一原因是效率。 @IhorDobrovolskyi 其他原因是 1) 更少的内存使用和 2) 适用于旧版本的 Octave(我发现这在 HPC 中很常见)。此外,accumdimaccumarrayaccumdim 的更复杂但更灵活的版本)是(曾经)这类问题的典型答案,对我来说似乎很容易阅读。我想可读性是相对的,可能取决于您对这些功能与自动广播的使用程度。【参考方案2】:

您可以将其视为矩阵乘法问题。例如,对于您的示例,这对应于

A = [1 2; 3 4; 4 5];
B = [0.5,0,0.5;0,1,0];

C = B*A

主要问题是以有效的方式从您的索引列表中构造B。我的建议是使用 == 的隐式扩展。

A = [1 2; 3 4; 4 5]; % Input data
idx = [1;2;1]; % Input Grouping

k = 2; % number of groups, ( = max(idx) )
m = 3; % Number of "observations"
Btmp = (idx == 1:k)'; % Mark locations
B = Btmp ./sum(Btmp,2); % Normalise
C = B*A

C =

    2.5000    3.5000
    3.0000    4.0000

【讨论】:

似乎 Btmp 可以更容易地构建:(idx == 1:k)'。这里应用了自动广播操作,所以不需要repmat。 @IhorDobrovolskyi,对,我一直忘记这一点,现在是一件事。你还记得是否有任何加速吗? 我不认为有任何合理的加速,但是它应该节省一些内存。 而且拥有更可读的代码也是使用自动广播的一个很好的理由,所以我一直更喜欢这种方式。

以上是关于计算 Octave 中行组的列的平均值的主要内容,如果未能解决你的问题,请参考以下文章

计算组的平均值,同时保留对象类型的列

如何计算另一列中特定值的列的平均值?

在计算 Pandas 创建的数据框中的列的平均值时指定“跳过 NA”

8.聚集函数 ---SQL

如何在Python中按十年计算列的平均值

仅计算“今天”之前的日期列的平均值