MATLAB:条件求和

时间:2011-11-06 01:33:25

标签: matlab

我有两个以下形式的数组:

v1 = [ 1 2 3 4 5 6 7 8 9 ... ]
c2 = { 'a' 'a' 'a' 'b' 'b' 'c' 'c' 'c' 'c' ... }

(所有值仅为示例,在实际数据中不能假设模式。v1c2具有相同的大小)

我想获得一个向量,其中包含与v1中相等值对应的c2分量的总和。在上面的示例中,结果向量的第一个分量为1+2+3,第二个4+5,依此类推。

我知道我可以在表格的循环中完成:

uni_c2 = unique(c2);
result = zeros(size(uni_c2));
for i = 1:numel(uni_c2)
     result(i) = sum( v1(strcmp(uni_c2(i),c2)) );
end 

是否有单一命令或矢量化方式进行相同的操作?

3 个答案:

答案 0 :(得分:3)

您可以分两行进行:

[b, m, n] = unique(c2)
result = accumarray(n', v1)

结果元素对应于单元格数组b中的字符串。

答案 1 :(得分:1)

这是矢量化但对于非常大的矢量来说是一个坏主意。对于某些问题,“矢量化”解决方案比for循环更差。

>> v1 = [ 1 2 3 4 5 6 7 8 9];
>> c2 = 'aaabbcccc'-'a'
c2 =
   0   0   0   1   1   2   2   2   2
>> N = repmat(c2',1,max(c2)-min(c2)+1) == repmat([min(c2):max(c2)],size(c2,2),1);
>> v1*N
ans =
    6    9   30

答案 2 :(得分:0)

我认为一个非常通用(和矢量化)的解决方案是这样的:

v1 = [ 1 2 3 4 5 6 7 8 9  ]
c2 = { 'a' 'a' 'a' 'b' 'b' 'c' 'c' 'c' 'c'  }
uniqueValuesInC2 = unique(c2);
conditionalSumOfV1 = @(x)(sum(v1(strcmp(c2, x))));
result = cellfun(conditionalSumOfV1, uniqueValuesInC2)

也许我的解决方案需要对未经训练的眼睛进行一些解释:

首先,您实际需要在c2中计算不同的可能值,这由unique完成。

conditionalSumOfV1函数接受参数x,它将c2中的每个元素与x进行比较,并选择v1中的相应元素并对它们求和。

最后cellfun与其他语言中的foreach构造相当:函数conditionalSum将针对您提供的单元格数组中的每个值进行求值(在这种情况下:每个唯一值在c2)并将其存储在输出数组中。对于其他类型的容器变量(数组,结构),MATLAB具有等效的foreach - 类似结构:arrayfunstructfun

这适用于长度超过单个字符的c2内容,并且不需要大型repmat操作作为stardt的解决方案。然而,当涉及c2只有几个重复值的长数组时,我确实有疑问。但我想这对于大多数算法来说都是一个难题。如果您遇到这种情况,您可能需要查看unique的额外输出或编写自己的unique替代(即写for循环,最好是在编译中语言/ MEX)。