Pregunta

Mi pregunta es similar a esta una, pero me gustaría replicar cada elemento de acuerdo con un recuento especificado en una segunda matriz del mismo tamaño.

Un ejemplo de esto, digamos que tenía una matriz v = [3 1 9 4], Quiero usar rep = [2 3 1 5] para replicar el primer elemento 2 veces, el segundo tres veces, y así sucesivamente para obtener [3 3 1 1 1 9 4 4 4 4 4].

Hasta ahora estoy usando un bucle simple para hacer el trabajo. Esto es con lo que empecé:

vv = [];
for i=1:numel(v)
    vv = [vv repmat(v(i),1,rep(i))];
end

Me las arreglé para mejorar el espacio preallocador:

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

Sin embargo, todavía siento que tiene que haber una forma más inteligente de hacer esto ... gracias

¿Fue útil?

Solución

Aquí hay una forma en que me gusta lograr esto:

>> 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

Esto funciona primero creando un vector de índice de cero la misma longitud que el recuento final de todos los valores. Realizando una suma acumulativa del rep Vector con el último elemento eliminado y un 1 colocado al comienzo, obtengo un vector de índices en index mostrando dónde comenzarán los grupos de valores replicados. Estos puntos están marcados con los. Cuando se realiza una suma acumulada en index, Obtengo un vector de índice final en el que puedo usar para indexar en el v Para crear el vector de valores heterogéneamente replicados.

Otros consejos

Para agregar a la lista de posibles soluciones, considere esta:

vv = cellfun(@(a,b)repmat(a,1,b), num2cell(v), num2cell(rep), 'UniformOutput',0);
vv = [vv{:}];

Esto es mucho más lento que el de hendedero..

Lo que estás tratando de hacer es decodificación de longitud de ejecución. Una utilidad confiable/vectorizada de alto nivel es la Presentación de FEX rude():

% example inputs
counts = [2, 3, 1];
values = [24,3,30];

el resultado

rude(counts, values)
ans =
    24    24     3     3     3    30

Tenga en cuenta que esta función realiza la operación opuesta también, es decir codificaciones de longitud de ejecución un vector o en otras palabras regresa values y el correspondiente counts.

accumarray la función se puede usar para que el código funcione si ceros sale en rep formación

function vv = repeatElements(v, rep)
index = accumarray(cumsum(rep)'+1, 1);
vv = v(cumsum(index(1:end-1))+1);
end

Esto funciona de manera similar a la solución de Gnovice, excepto que los índices se acumulan en lugar de asignarse a 1. Esto permite omitir algunos índices (3 y 6 en el ejemplo a continuación) y eliminar los elementos correspondientes de la salida.

>> 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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top