Replicación de matriz de elementos según un recuento [duplicado
-
24-09-2019 - |
Pregunta
Esta pregunta ya tiene una respuesta aquí:
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
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