MATLAB: duplication du vecteur' n ' times [dupliquer]
Cette question a déjà une réponse ici:
- Octave / Matlab: étendre un vecteur le faisant se répéter? 2 réponses
j'ai un vecteur, par exemple,
vector = [1 2 3]
je voudrais dupliquer à l'intérieur de lui-même n fois, c'est à dire si n = 3, ce serait la fin de la manière suivante:
vector = [1 2 3 1 2 3 1 2 3]
Comment puis-je atteindre cet pour toute valeur de n? Je sais que je pourrais faire ce qui suit:
newvector = vector;
for i = 1 : n-1
newvector = [newvector vector];
end
Cela semble un peu lourd. Aucune des méthodes plus efficaces?
3 réponses
repmat([1 2 3],1,3)
je vous laisse consulter la documentation repmat
.
C'est une méthode plus rapide que repmat
ou reshape
par un Ordre de Grandeur
une des meilleures méthodes pour faire de telles choses est D'utiliser Le truc de Tony. Repmat et Reshape sont généralement plus lents que Tony, car ils utilisent directement L'indexation inhérente à Matlabs. Pour répondre à votre question,
disons, que vous voulez carreler le vecteur de ligne r=[1 2 3]
N
fois r=[1 2 3 1 2 3 1 2 3...]
, puis
c=r'
cc=c(:,ones(N,1));
r_tiled = cc(:)';
Cette méthode a économies de temps importantes par rapport à reshape
ou repmat
pour les grandes N
.
EDIT: réponse aux doutes de @Li-Aung Yip
j'ai effectué un petit test de Matlab pour vérifier le différentiel de vitesse entre repmat
et tony's trick
. En utilisant le code mentionné ci-dessous, j'ai calculé les temps pour construire le même vecteur de carrelage à partir d'un vecteur de base A=[1:N]
. Les résultats montrent que oui, le tour de Tony est plus rapide D'un ordre de grandeur, surtout pour les plus grands N. Les gens sont invités à essayer eux-mêmes. Ce grand différentiel de temps peut être critique si une telle opération doit être effectuée en boucles. Voici le petit script que j'ai utilisé;
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
Le Temps (en secondes) pour les deux méthodes sont donnés ci-dessous;
- N= 10, time_repmat = 8e - 5, time_tony = 3e-5
- N= 100, time_repmat = 2.9 e - 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
mon RAM ne m'a pas permis d'aller au-delà de N=10000. Je suis sûr que la différence de temps entre les deux méthodes sera encore plus significative pour N=100000. Je sais, ces temps peuvent être différents pour différentes machines, mais la différence relative dans l'ordre de grandeur des temps sera maintenue. Aussi, je sais, la moyenne de temps aurait pu être une meilleure métrique, mais je voulais juste montrer l'ordre de grandeur de la différence de consommation de temps entre les deux approches. Ma machine/os de détails sont donnés ci-dessous :
détails pertinents de la Machine / OS / Matlab : Athlon i686 Arc, Ubuntu 11.04 32 bits, 3 go de ram, Matlab, 2011b
basé sur la réponse D'Abhinav et quelques tests, j'ai écrit une fonction qui est toujours plus rapide que repmat()!
Il utilise les mêmes paramètres, sauf pour le premier paramètre qui doit être un vecteur et non une matrice.
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
N'hésitez pas à tester la fonction avec toutes vos données et me donner des commentaires. Quand tu as trouvé quelque chose pour l'améliorer, dis-le-moi.