How to vectorize row-wise diagonalization of a matrix

后端 未结 4 1641
無奈伤痛
無奈伤痛 2021-01-21 16:33

I have an n-by-m matrix that I want to convert to a mn-by-m matrix, with each m-by-m block of the result containing the diagonal of each row.

For example, if the input i

相关标签:
4条回答
  • 2021-01-21 17:06

    For a vectorized way to do this, create the linear indices of the diagonal elements into the resulting matrix, and assign directly.

    %# create some input data
    inArray = [10 11;12 13;14 15];
    
    %# make the index array
    [nr,nc]=size(inArray);
    
    idxArray = reshape(1:nr*nc,nc,nr)';
    idxArray = bsxfun(@plus,idxArray,0:nr*nc:nr*nc^2-1);
    
    %# create output
    out = zeros(nr*nc,nc);
    out(idxArray) = inArray(:);
    
    out =
    
        10     0
         0    11
        12     0
         0    13
        14     0
         0    15
    
    0 讨论(0)
  • 2021-01-21 17:14

    Here's a simple vectorized solution, assuming X is the input matrix:

    Y = repmat(eye(size(X, 2)), size(X, 1), 1);
    Y(find(Y)) = X;
    

    Another alternative is to use sparse, and this can be written as a neat one-liner:

    Y = full(sparse(1:numel(X), repmat(1:size(X, 2), 1, size(X, 1)), X'));
    
    0 讨论(0)
  • 2021-01-21 17:18

    The easiest way I see to do this is actually quite simple, using simple index referencing and the reshape function:

    I = [1 2; 3 4; 5 6];
    J(:,[1,4]) = I;
    K = reshape(J',2,6)';
    

    If you examine J, it looks like this:

    J =
         1     0     0     2
         3     0     0     4
         5     0     0     6
    

    Matrix K is just what wanted:

    K =
         1     0
         0     2
         3     0
         0     4
         5     0
         0     6
    

    As Eitan T has noted in the comments, the above is specific to the example, and doesn't cover the general solution. So below is the general solution, with m and n as described in the question.

    J(:,1:(m+1):m^2) = I;
    K=reshape(J',m,m*n)';
    

    If you want to test it to see it working, just use

    I=reshape(1:(m*n),m,n)';
    

    Note: if J already exists, this can cause problems. In this case, you need to also use

    J=zeros(n,m^2);
    
    0 讨论(0)
  • 2021-01-21 17:26

    It may not be the most computationally efficient solution, but here's a 1-liner using kron:

    A = [1 2; 3 4; 5 6];
    B = diag(reshape(A', 6, 1) * kron(ones(3, 1), eye(2))
    % B = 
    %     1     0
    %     0     2
    %     3     0
    %     0     4
    %     5     0
    %     0     6
    

    This can be generalized if A is n x m:

    diag(reshape(A.', n*m, 1)) * kron(ones(n,1), eye(m))
    
    0 讨论(0)
提交回复
热议问题