MATLAB:accumarray,矩阵为值(第二个输入参数)

MATLAB:accumarray,矩阵为值(第二个输入参数),matlab,matrix,accumarray,Matlab,Matrix,Accumarray,我有一个带有percantage值的矩阵,其中每一行代表一个单独的观察值。我需要计算这些值对应于相同下标的累积积。我尝试使用accumarray函数,只要使用列向量作为值(而不是矩阵),该函数就可以正常工作。 我想知道什么是最好的方法来解决我的问题,而不循环通过我的价值矩阵的各个列 以下是我的示例代码: subs = [1;1;1;2;2;2;2;2;3;3;4;4;4]; vals1 = [0.1;0.05;0.2;0.02;0.09;0.3;0.01;0.21;0.12;0.06;0.08;

我有一个带有percantage值的矩阵,其中每一行代表一个单独的观察值。我需要计算这些值对应于相同下标的累积积。我尝试使用
accumarray
函数,只要使用列向量作为值(而不是矩阵),该函数就可以正常工作。 我想知道什么是最好的方法来解决我的问题,而不循环通过我的价值矩阵的各个列

以下是我的示例代码:

subs = [1;1;1;2;2;2;2;2;3;3;4;4;4];
vals1 = [0.1;0.05;0.2;0.02;0.09;0.3;0.01;0.21;0.12;0.06;0.08;0.12;0.05];

% This is working as expected
result1 = accumarray(subs,vals1, [], @(x) prod(1+x) -1)


vals2 = [vals1,vals1];

% This is not working as the second input parameter of accumarray
% apperently must be a vector (rather than a matrix)
result2 = accumarray(subs, vals2, [], @(x) prod(1+x) -1)

对于VAL,您可以将其设置为
1:size(vals2,1)
,并使用它提取
vals2
的行。函数还需要返回单元格

result2 = accumarray(subs, 1:size(vals2,1), [], @(x) {prod(1+vals2(x,:),1)-1})
可以连接单元元素:

result3 = vertcat(result2{:})
或全部在一行中:

result3 = cell2mat( accumarray(subs, 1:size(vals2,1), [], @(x) {prod(1+vals2(x,:),1)-1}))

result3 =

   0.38600   0.38600
   0.76635   0.76635
   0.18720   0.18720
   0.27008   0.27008
使用
[10000 x 200]
矩阵作为输入,比较三种建议方法的倍频程测试结果:

subs = randi(1000,10000,1);
vals2 = rand(10000,200);

=========CELL2MAT========
Elapsed time is 0.130961 seconds.
=========NDGRID========
Elapsed time is 3.96383 seconds.
=========FOR LOOP========
Elapsed time is 6.16265 seconds.

您需要向添加第二组下标(使其为N×2)以处理2D数据,该数据仍然必须作为N元素向量传递(即
子文件中每行一个元素)。可以使用以下方法生成新的二维下标集:

以及您的样本数据的结果:

result2 =

    0.3860    0.3860
    0.7664    0.7664
    0.1872    0.1872
    0.2701    0.2701

这看起来不是一个简单的解决方案。它正在工作,但在imho中,它使accumarray函数的可读性降低。在这种情况下,我想我更喜欢一个简单的for循环解决方案
对于i=1:size(vals2,2)
result2(:,i)=accumarray(subs,vals2(:,i),[],@(x)产品(1+x)-1)
end
当列数较多时,for循环解决方案可能效率较低。嗯,在我的情况下,列数可能高达10000。@rahnema1我认为OP发布的for循环解决方案效率不高。我在没有accumarray的情况下实现了一个改进的for循环,它的运行速度与cell2mat一样快。我修改了您的脚本并添加了改进的for循环解决方案。运行几次,您将看到性能与cell2mat类似。老实说,我有点惊讶于simple for循环与accumarray匹配。如果我遗漏了什么,请告诉我。@Turbo我编辑了代码,并为
subs
使用了随机数据集。有
1500个
独特类别,每个类别最多重复500次。我注释掉了ndgrid,因为它需要大量内存。改进的循环比未改进的循环好,但其性能无法超过
cell2mat
。最好使用
repelem
创建数据集,但该版本的倍频程不包含
repelem
。如果
vals2
中的列数是可变的,您将如何定义
ngrid
的输出参数?@Andi:这正是我在上述代码中所做的。请注意,
ndgrid
的第二个参数是从1到
size(vals2,2)
的向量(即
vals2
中的列数)。
result2 =

    0.3860    0.3860
    0.7664    0.7664
    0.1872    0.1872
    0.2701    0.2701