我有两个以下形式的数组:
v1 = [ 1 2 3 4 5 6 7 8 9 ... ]
c2 = { 'a' 'a' 'a' 'b' 'b' 'c' 'c' 'c' 'c' ... }
(所有值仅为示例,在实际数据中不能假设模式。v1
和c2
具有相同的大小)
我想获得一个向量,其中包含与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
是否有单一命令或矢量化方式进行相同的操作?
答案 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
- 类似结构:arrayfun
,structfun
。
这适用于长度超过单个字符的c2
内容,并且不需要大型repmat
操作作为stardt的解决方案。然而,当涉及c2
只有几个重复值的长数组时,我确实有疑问。但我想这对于大多数算法来说都是一个难题。如果您遇到这种情况,您可能需要查看unique
的额外输出或编写自己的unique
替代(即写for
循环,最好是在编译中语言/ MEX)。