MATLAB: Subtracting matrix subsets by specific rows

后端 未结 5 1762
刺人心
刺人心 2020-12-03 19:22

Here is an example of a subset of the matrix I would like to use:

1 3 5

2 3 6

1 1 1

3 5 4

5 5 5

8 8 0

5条回答
  •  暖寄归人
    2020-12-03 20:07

    a slightly shorter and vectorized way will be (if a is your matrix) :

    b=a-kron(a(1:3:end,:),ones(3,1));
    

    let's test:

    a=[1 3 5
       2 3 6
       1 1 1
       3 5 4
       5 5 5
       8 8 0]
    
    a-kron(a(1:3:end,:),ones(3,1))
    
    ans =
     0     0     0
     1     0     1
     0    -2    -4
     0     0     0
     2     0     1
     5     3    -4
    

    Edit

    Here's a bsxfun solution (less elegant, but hopefully faster):

    a-reshape(bsxfun(@times,ones(1,3),permute(a(1:3:end,:),[2 3 1])),3,[])'
    
    ans =
    
     0     0     0
     1     0     1
     0    -2    -4
     0     0     0
     2     0     1
     5     3    -4
    

    Edit 2

    Ok, this got me curios, as I know bsxfun starts to be less efficient for bigger array sizes. So I tried to check using timeit my two solutions (because they are one liners it's easy). And here it is:

    range=3*round(logspace(1,6,200));
    for n=1:numel(range)
        a=rand(range(n),3);
        f=@()a-kron(a(1:3:end,:),ones(3,1));
        g=@() a-reshape(bsxfun(@times,ones(1,3),permute(a(1:3:end,:),[2 3 1])),3,[])';
        t1(n)=timeit(f);
        t2(n)=timeit(g);
    end
    semilogx(range,t1./t2);
    

    enter image description here

    So I didn't test for the for loop and Divkar's bsxfun, but you can see that for arrays smaller than 3e4 kron is better than bsxfun, and this changes at larger arrays (ratio of <1 means kron took less time given the size of the array). This was done at Matlab 2012a win7 (i5 machine)

提交回复
热议问题