【问题标题】:Summing elements of different range for each row and replace对每行不同范围的元素求和并替换
【发布时间】:2015-05-30 09:42:57
【问题描述】:
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 6 列之间的元素来执行条件。等等……

条件:对指定元素求和,然后用计算的和替换相关行的所有元素。比如A包含0,0,4(和为0+0+4=4),那么矩阵C第一行的所有元素都写4。

没有for循环,只有矩阵运算,这个任务怎么做?

【问题讨论】:

    标签: matlab matrix


    【解决方案1】:

    一种基于repelem@colon notationaccumarray 的方法-

    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;
    

    【讨论】:

    • arrayfun(@colon, ...) 对我来说是个新闻!太好了!
    • @LuisMendo 是的,这个新东西终于有点用处了! :)
    • arrayfun(@colon,...) 很聪明。 +1。
    【解决方案2】:

    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);
    

    【讨论】:

      【解决方案3】:

      @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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-27
        • 1970-01-01
        • 1970-01-01
        • 2019-05-14
        • 1970-01-01
        • 2019-06-14
        • 2021-08-09
        • 1970-01-01
        相关资源
        最近更新 更多