Replicação da matriz em termos de elemento de acordo com uma contagem [duplicata
-
24-09-2019 - |
Pergunta
Esta pergunta já tem uma resposta aqui:
Minha pergunta é semelhante a isso 1, mas eu gostaria de replicar cada elemento de acordo com uma contagem especificada em uma segunda matriz do mesmo tamanho.
Um exemplo disso, digamos que eu tive uma matriz v = [3 1 9 4]
, Eu quero usar rep = [2 3 1 5]
para replicar o primeiro elemento 2 vezes, o segundo três vezes, e assim por diante para obter [3 3 1 1 1 9 4 4 4 4 4]
.
Até agora, estou usando um loop simples para fazer o trabalho. Isso é com o que eu comecei:
vv = [];
for i=1:numel(v)
vv = [vv repmat(v(i),1,rep(i))];
end
Consegui melhorar o espaço pré -alocado:
vv = zeros(1,sum(rep));
c = cumsum([1 rep]);
for i=1:numel(v)
vv(c(i):c(i)+rep(i)-1) = repmat(v(i),1,rep(i));
end
No entanto, ainda sinto que deve haver uma maneira mais inteligente de fazer isso ... obrigado
Solução
Aqui está uma maneira de eu gostar de conseguir isso:
>> index = zeros(1,sum(rep));
>> index(cumsum([1 rep(1:end-1)])) = 1;
index =
1 0 1 0 0 1 1 0 0 0 0
>> index = cumsum(index)
index =
1 1 2 2 2 3 4 4 4 4 4
>> vv = v(index)
vv =
3 3 1 1 1 9 4 4 4 4 4
Isso funciona primeiro criando um vetor de índice de zeros do mesmo comprimento que a contagem final de todos os valores. Realizando uma soma cumulativa do rep
vetor com o último elemento removido e 1 colocado no início, eu recebo um vetor de índices em index
mostrando onde os grupos de valores replicados começarão. Esses pontos são marcados com outros. Quando uma soma cumulativa é realizada em index
, Recebo um vetor de índice final que posso usar para indexar em v
Para criar o vetor de valores replicados heterogeneamente.
Outras dicas
Para adicionar à lista de soluções possíveis, considere esta:
vv = cellfun(@(a,b)repmat(a,1,b), num2cell(v), num2cell(rep), 'UniformOutput',0);
vv = [vv{:}];
Isso é muito mais lento que o de gnovice..
O que você está tentando fazer é Decodificação do comprimento da execução. Um utilitário de alto nível confiável/vetorizado é o Submissão Fex rude()
:
% example inputs
counts = [2, 3, 1];
values = [24,3,30];
o resultado
rude(counts, values)
ans =
24 24 3 3 3 30
Observe que esta função também executa a operação oposta, ou seja, codas de comprimento de corrida um vetor ou em outras palavras retorna values
e o correspondente counts
.
accumarray
A função pode ser usada para fazer o código funcionar se os zeros sair rep
variedade
function vv = repeatElements(v, rep)
index = accumarray(cumsum(rep)'+1, 1);
vv = v(cumsum(index(1:end-1))+1);
end
Isso funciona semelhante à solução do GNOVICE, exceto que os índices são acumulados sendo atribuídos a 1. Isso permite pular alguns índices (3 e 6 no exemplo abaixo) e remover os elementos correspondentes da saída.
>> v = [3 1 42 9 4 42];
>> rep = [2 3 0 1 5 0];
>> index = accumarray(cumsum(rep)'+1, 1)'
index =
0 0 1 0 0 2 1 0 0 0 0 2
>> cumsum(index(1:end-1))+1
ans =
1 1 2 2 2 4 5 5 5 5 5
>> vv = v(cumsum(index(1:end-1))+1)
vv =
3 3 1 1 1 9 4 4 4 4 4