20

I have a vector, e.g.

vector = [1 2 3] 

I would like to duplicate it within itself n times, i.e. if n = 3, it would end up as:

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

How can I achieve this for any value of n? I know I could do the following:

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

This seems a little cumbersome though. Any more efficient methods?

0

3 Answers 3

39

Try

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

I'll leave you to check the documentation for repmat.

Sign up to request clarification or add additional context in comments.

Comments

20

This is a Faster Method Than repmat or reshape by an Order of Magnitude

One of the best methods for doing such things is Using Tony's Trick. Repmat and Reshape are usually found to be slower than Tony's trick as it directly uses Matlabs inherent indexing. To answer you question,

Lets say, you want to tile the row vector r=[1 2 3] N times like r=[1 2 3 1 2 3 1 2 3...], then,

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

This method has significant time savings against reshape or repmat for large N's.

EDIT : Reply to @Li-aung Yip's doubts

I conducted a small Matlab test to check the speed differential between repmat and tony's trick. Using the code mentioned below, I calculated the times for constructing the same tiled vector from a base vector A=[1:N]. The results show that YES, Tony's-Trick is FASTER BY AN ORDER of MAGNITUDE, especially for larger N. People are welcome to try it themselves. This much time differential can be critical if such an operation has to be performed in loops. Here is the small script I used;

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 

The Times (in seconds) for both methods are given below;

  • 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

My RAM didn't permit me to go beyond N=10000. I am sure, the time difference between the two methods will be even more significant for N=100000. I know, these times might be different for different machines, but the relative difference in order-of-magnitude of times will stand. Also, I know, the avg of times could have been a better metric, but I just wanted to show the order of magnitude difference in time consumption between the two approaches. My machine/os details are given below :

Relevant Machine/OS/Matlab Details : Athlon i686 Arch, Ubuntu 11.04 32 bit, 3gb ram, Matlab 2011b

6 Comments

Firstly; What?! Secondly, one wonders why repmat() is slower than doing it 'manually'. Thirdly, anyone who uses this better put a comment next to it...
After some research into Tony's Trick, it appears that it was faster at the time of writing - 14 years ago. MATLAB has improved a lot since then, and Tony's Trick may not be faster than repmat any more. (You should write a benchmark and test this. ;) )
Will do, thanks for the links.
Excellent answer: a statement about program performance backed up by evidence. I see lots of assertions about program performance here on SO, very few backed up by evidence. I can't see myself using Tony's Trick regularly but then I don't use repmat much, and now I know where to look if I ever find repmat too slow.
UPDATE FOR 2018 I replicated the above experiment (do put your code to be timed in a function M-file!), and got consistently faster results with repmat. That said, even repmat is outdated, we have had bsxfun for over a decade, and now have implicit singleton expansion. Legitimate uses of repmat are very few and far between nowadays.
|
4

Based on Abhinav's answer and some tests, I wrote a function which is ALWAYS faster than repmat()!

It uses the same parameters, except for the first parameter which must be a vector and not a matrix.

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 

Feel free to test the function with all your data and give me feedback. When you found something to even improve it, please tell me.

1 Comment

Always faster? Can we see some numbers, cross-platform/OS/vector size/etc.?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.