Replicate vector and shift each copy by 1 row down without for-loop

前端 未结 2 1507
北恋
北恋 2020-12-12 00:31

I would like replicate a vector N times to create a matrix with each copy shifted 1 row down. See image (first column is the vector 1 to 5). It would be great i

相关标签:
2条回答
  • 2020-12-12 00:43

    Solution Code

    This seems to be a fast approach based on repmat and bsxfun as the benchmarks listed in the next section might convince us -

    %// Concatenate one zero at the end of a column vector version of the input vector.
    %// Then, replicate the whole vector along columns to have a 2D matrix. 
    %// Then "progressively" set elements from each column as zeros corresponding 
    %// to the starting zeros of the desired output.
    val = repmat([A(:);0],1,N).*bsxfun(@le,[1:N+1]',N:-1:1);  %//'
    
    %// Chop-off at N x N length and reshape to have the final output
    out = reshape(val(1:N*N),N,N);
    

    Benchmarking

    In this section we will cover runtime benchmarking for the various approaches listed on this page for the stated problem.

    Benchmarking Code -

    %datasizes = [10 20 50 70 100 200 500 700 1000]; %// Set -1
    datasizes = [1000 2000 5000 7000 10000];         %// Set -2
    fcns = {'repvecshiftdown_flipud_hankel','repvecshiftdown_toeplitz',...
    'repvecshiftdown_repmat_bsxfun','repvecshiftdown_tril_toeplitz'};%//approaches
    tsec = zeros(numel(fcns),numel(datasizes));
    
    for k1 = 1:numel(datasizes),
        A = randi(9,1,datasizes(k1)); %// Creare random input vector
        for k2 = 1:numel(fcns), %// Time approaches  
            tsec(k2,k1) = timeit(@() feval(fcns{k2}, A), 1);
            fprintf('\tFunction: %s (%3.2f sec)\n',fcns{k2},tsec(k2,k1));
        end
    end
    
    figure;  %% Plot Runtimes
    plot(datasizes,tsec(1,:),'-rx'), hold on
    plot(datasizes,tsec(2,:),'-bo')
    plot(datasizes,tsec(3,:),'-k+')
    plot(datasizes,tsec(4,:),'-g.')
    set(gca,'xgrid','on'),set(gca,'ygrid','on'),
    xlabel('Datasize (# elements)'), ylabel('Runtime (s)')
    legend(upper(strrep(fcns,'_',' '))),title('Runtime')
    

    Associated function codes (all approaches) -

    function out = repvecshiftdown_repmat_bsxfun(A)
    N = numel(A);
    val = repmat([A(:);0],1,N).*bsxfun(@le,[1:N+1]',[N:-1:1]); %//'
    out = reshape(val(1:N*N),N,N);
    return;
    
    function out = repvecshiftdown_tril_toeplitz(A)
    out = tril( toeplitz(A) );
    return;
    
    function out = repvecshiftdown_toeplitz(A)
    out = toeplitz(A, zeros(size(A)));
    return;
    
    function out = repvecshiftdown_flipud_hankel(A)
    out = flipud( hankel( flipud(A(:)) ) );
    return;
    

    Runtime plots -

    Set #1 [From 10 till 1000 datasizes]:

    enter image description here

    Set #2 [From 1000 till 10000 datasizes]:

    enter image description here

    0 讨论(0)
  • 2020-12-12 00:46

    You can do it with toeplitz and tril;

    a = [1 2 3 4 5]
    out = tril( toeplitz(a) )
    

    or

    out = toeplitz(a, a*0)
    %// out = toeplitz(a, zeros(size(a)) )  %// for large arrays
    

    or if you don't mind some happy flipping:

    out = flipud( hankel( flipud(a(:)) ) )
    
    0 讨论(0)
提交回复
热议问题