Uma function semelhante ao representante de R em Matlab

Eu estou procurando uma function que se comporta de forma semelhante à function rep em R para Matlab. Por exemplo, com rep eu posso fazer o seguinte:

 > rep(c(1,2,3),times=3) [1] 1 2 3 1 2 3 1 2 3 > rep(c(1,2,3),each=3) [1] 1 1 1 2 2 2 3 3 3 > 

No matlab existe a function repmat que realiza a primeira parte

 >> repmat([1,2,3],1,3) ans = 1 2 3 1 2 3 1 2 3 

mas não a segunda parte (ou pelo menos eu não consigo descobrir como fazer isso).

Alguma sugestão?

Você pode reproduzir a syntax da function rep em R de perto, primeiro definindo uma function da seguinte maneira:

 function [result]=rep(array, count) matrix = repmat(array, count,1); result = matrix(:); 

Em seguida, você pode reproduzir o comportamento desejado chamando um vetor de linha ou coluna:

 >> rep([1 2 3],3) ans = 1 1 1 2 2 2 3 3 3 >> rep([1 2 3]',3) ans = 1 2 3 1 2 3 1 2 3 

Observe que usei o operador transpose (‘) na segunda chamada para passar a matriz de input como um vetor de coluna (uma matriz 3×1).

Eu testei isso no meu laptop, e para um array base com 100.000 elementos repetidos 100 vezes, foi entre 2 a 8 vezes mais rápido do que usar a opção ceil acima, dependendo se você quer o primeiro ou o segundo arranjo.

Boa pergunta +1. Um método simples de uma linha para isso é através do produto tensorial Kronecker, por exemplo:

 A = [1 2 3]; N = 3; B = kron(A, ones(1, N)); 

Então:

 B = 1 1 1 2 2 2 3 3 3 

UPDATE: @Dan forneceu uma solução muito legal que parece ser mais eficiente do que o meu método kron , então verifique isso antes de sair da página 🙂

UPDATE: @bcumming também forneceu uma boa solução que deve ser muito bem dimensionada quando o vetor de input é grande.

Se você gosta de mim, você não tem idéia do que é um produto tensorial da Kronecker, você pode estar interessado nesta solução mais intuitiva (e, na verdade, acho que é mais rápida):

 c(ceil((1:length(c)*n)/n)); 

então aqui eu usei indexação vetorial para replicar a matriz. Por exemplo, usando os dois casos que você tem acima, poderíamos fazer:

 c = 1:3; c([1 1 1 2 2 2 3 3 3]) %for each c([1 2 3 1 2 3 1 2 3]) %for times 

então as perguntas são como fazemos um vetor [1 2 3 1 2 3 1 2 3] sem a própria funcionalidade que você está solicitando. Então, eu fiz um vetor com o número de elementos que precisamos, ou seja, 1: 9 e, em seguida, dividir por três e arredondar para cima (ou seja, tente ceil((1:9)/3) na linha de comando.

Um pouco de benchmarking (eu sei que essas coisas devem estar em loop, então talvez isso não seja tão preciso):

 c = 1:3; n = 3; tic; k = kron(c, ones(1, n)); toc; % 0.000208 seconds. tic; a = c(ceil((1:length(c)*n)/n)); toc; % 0.000025 seconds. clear; c = 1:1000000; n = 3; tic; k = kron(c, ones(1, n)); toc; % 0.143747 seconds. tic; a = c(ceil((1:length(c)*n)/n)); toc; % 0.090956 seconds. clear; c = 1:10000; n = 1000; tic; k = kron(c, ones(1, n)); toc; % 0.583336 seconds. tic; a = c(ceil((1:length(c)*n)/n)); toc; % 0.237878 seconds. 

Aqui está uma ideia:

 a=[1,2,3]; reshape(repmat(a,1,length(a)),1,length(a)^2) ans = 1 2 3 1 2 3 1 2 3 reshape(repmat(a,length(a),1),1,length(a)^2) ans = 1 1 1 2 2 2 3 3 3 

Ainda não consigo encontrar uma function mais simples que faça isso em uma etapa, interessada se houver uma.