A = [-1,-1,0,0,4,1,3,0,1,1;
-1,1,1,0,2,1,1,0,0,1;
0,0,1,0,1,0,1,0,2,0];
B = [3,5;
2,6;
1,7];
预期输出单元阵列(一列):
C = [4,4,4,4,4,4,4,4,4,4; %// sum of elements 3,4,5 is 4
5,5,5,5,5,5,5,5,5,5; %// sum of elements 2,3,4,5,6 is 5
3,3,3,3,3,3,3,3,3,3]; %// sum of elements 1,2,3,4,5,6,7 is 3
矩阵B包括应该使用哪些列来执行矩阵A上的条件。例如,B的第一行是3和5;因此,矩阵A的第3列和第5列之间的元素应该用于执行条件。 B的第二行是2和6;所以应该使用第2列之间的元素来执行条件。等等...
条件:对指定的元素求和,然后用计算的和替换相关行的所有元素。例如,A包括0,0,4(sum为0 + 0 + 4 = 4),因此将4写入矩阵C的第一行的所有元素。
没有for循环,只有矩阵运算,我该如何完成这项任务?
答案 0 :(得分:4)
基于repelem
,@colon notation
& accumarray
-
id = repelem(1:size(B,1),diff(B,[],2)+1)
extents_cell = arrayfun(@colon, B(:,1), B(:,2), 'Uni', 0)
rowval = accumarray(id(:),A(sub2ind(size(A),id,[extents_cell{:}])))
C = repmat(rowval,1,size(A,2))
请注意,repelem
仅支持MATLAB 2015a
。因此,如果您无法访问它,则可以使用this answer
中列出的自定义版本来计算id
,或者像这样 -
id = repelem_custom(1:size(B,1),diff(B,[],2).'+1)
替换repelem
的自定义函数看起来像这样 -
function out = repelem_custom(vals,runlens)
clens = cumsum(runlens);
idx = zeros(1,(clens(end)));
idx([1 clens(1:end-1)+1]) = diff([0 vals]);
out = cumsum(idx);
return;
答案 1 :(得分:3)
使用bsxfun
:
n = size(A,2);
jj = 1:n;
C = repmat(sum(A .* (bsxfun(@ge, jj, B(:,1)) & bsxfun(@le, jj, B(:,2))), 2), 1, n);
答案 2 :(得分:2)
@Divakar的arrayfun
我认为它不会那么高效,因为这个使用匿名函数而不是内置colon(:)
运算符
唯一的好消息是,它是一个单线
out = repmat(arrayfun(@(x,y,r) sum(A(r,x:y)),B(:,1),B(:,2),(1:size(A,1)).'),1,size(A,2))
示例输入的结果:
out =
4 4 4 4 4 4 4 4 4 4
5 5 5 5 5 5 5 5 5 5
3 3 3 3 3 3 3 3 3 3