web-dev-qa-db-ja.com

MATLAB:ベクトルを 'n'回複製する

私はベクトルを持っています、例えば.

vector = [1 2 3]

私はそれを複製したいと思いますそれ自体の中 n回、すなわち、n = 3の場合、それは次のようになります:

vector = [1 2 3 1 2 3 1 2 3]

Nの値に対してこれをどのように達成できますか?私は次のことができることを知っています:

newvector = vector;
for i = 1 : n-1
    newvector = [newvector vector];
end

ただし、これは少し面倒です。より効率的な方法はありますか?

19
CaptainProg

試して

repmat([1 2 3],1,3)

repmatのドキュメントを確認してください。

39

これはrepmatまたはreshapeよりも大きさのオーダーで高速な方法です

このようなことを行うための最良の方法の1つは、 [Tony's Trick。 を使用することです。通常、Matlabs固有のインデックス作成を直接使用するため、RepmatおよびReshapeはTonyのトリックよりも遅いことがわかります。あなたの質問に答えるために、

たとえば、行ベクトルをr=[1 2 3]のようにr=[1 2 3 1 2 3 1 2 3...]N回並べたい場合、

c=r'
cc=c(:,ones(N,1));
r_tiled = cc(:)';

このメソッドは、reshapeまたは大きなrepmatNに対して大幅に時間を節約します。

編集:@ Li-aung Yipの疑問に返信

repmattony's trickの速度差を確認するために、小さなMatlabテストを実施しました。下記のコードを使用して、ベースベクトルA=[1:N]から同じタイルベクトルを構築する時間を計算しました。その結果、YES、トニーのトリックはマグニチュードのオーダーにより速く、特により大きなNの場合、それを試してみてください。このような時間差は、このような操作をループで実行する必要がある場合に重要になることがあります。これが私が使用した小さなスクリプトです。

N= 10 ;% ASLO Try for values N= 10, 100, 1000, 10000

% time for tony_trick
tic;
A=(1:N)';
B=A(:,ones(N,1));
C=B(:)';
t_tony=toc;
clearvars -except t_tony N

% time for repmat
tic;
A=(1:N);
B=repmat(A,1,N);
t_repmat=toc;
clearvars -except t_tony t_repmat N

両方の方法の時間(秒)を以下に示します。

  • N = 10、time_repmat = 8e-5、time_tony = 3e-5
  • N = 100、time_repmat = 2.9e-4、time_tony = 6e-5
  • N = 1000、time_repmat = 0.0302、time_tony = 0.0058
  • N = 10000、time_repmat = 2.9199、time_tony = 0.5292

私のRAMは、N = 10000を超えることを許可しませんでした。2つの方法の時間差は、N = 100000でさらに重要になります。これらの時間は、マシンごとに異なりますが、時間の大きさの相対的な違いはそのままです。また、時間の平均がより良いメトリックである可能性がありますが、時間の大きさの違いの順序を表示したかっただけです。私のマシン/ OSの詳細を以下に示します:

関連マシン/ OS/Matlabの詳細:Athlon i686 Arch、Ubuntu 11.04 32ビット、3GB RAM、Matlab 2011b

19
Abhinav

Abhinavの回答といくつかのテストに基づいて、repmat()よりも常に高速な関数を作成しました。

同じパラメーターを使用しますが、最初のパラメーターは行列ではなくベクトルでなければなりません。

function vec = repvec( vec, rows, cols )
%REPVEC Replicates a vector.
%   Replicates a vector rows times in dim1 and cols times in dim2.
%   Auto optimization included.
%   Faster than repmat()!!!
%   
%   Copyright 2012 by Marcel Schnirring

    if ~isscalar(rows) || ~isscalar(cols)
        error('Rows and cols must be scaler')
    end

    if rows == 1 && cols == 1
        return  % no modification needed
    end

    % check parameters
    if size(vec,1) ~= 1 && size(vec,2) ~= 1
        error('First parameter must be a vector but is a matrix or array')
    end

    % check type of vector (row/column vector)
    if size(vec,1) == 1
        % set flag
        isrowvec = 1;
        % swap rows and cols
        tmp = rows;
        rows = cols;
        cols = tmp;
    else
        % set flag
        isrowvec = 0;
    end

    % optimize code -> choose version
    if rows == 1
        version = 2;
    else
        version = 1;
    end

    % run replication
    if version == 1
        if isrowvec
            % transform vector
            vec = vec';
        end

        % replicate rows
        if rows > 1
            cc = vec(:,ones(1,rows));
            vec = cc(:);
            %indices = 1:length(vec);
            %c = indices';
            %cc = c(:,ones(rows,1));
            %indices = cc(:);
            %vec = vec(indices);
        end

        % replicate columns
        if cols > 1
            %vec = vec(:,ones(1,cols));
            indices = (1:length(vec))';
            indices = indices(:,ones(1,cols));
            vec = vec(indices);
        end

        if isrowvec
            % transform vector back
            vec = vec';
        end
    elseif version == 2
        % calculate indices
        indices = (1:length(vec))';

        % replicate rows
        if rows > 1
            c = indices(:,ones(rows,1));
            indices = c(:);
        end

        % replicate columns
        if cols > 1
            indices = indices(:,ones(1,cols));
        end

        % transform index when row vector
        if isrowvec
            indices = indices';
        end

        % get vector based on indices
        vec = vec(indices);
    end
end

すべてのデータを使用して関数をテストし、フィードバックをお寄せください。さらに改善するものを見つけたら、教えてください。

4
darkdragon-001