Borrar filtros
Borrar filtros

Assigning array values to cell array based on condition

11 visualizaciones (últimos 30 días)
Dominik Rhiem
Dominik Rhiem el 13 de Dic. de 2021
Comentada: Dominik Rhiem el 21 de Dic. de 2021
I have two equally-sized vectors of indices like the following:
A = [1, 1, 1, 2, 2, 3, 3, 3, 3];
B = [6, 3, 7, 4, 7, 13, 16, 4, 1];
I want to assign the values of B into cell arrays based on the value of A at the same index, i.e.:
C{1} = B(A==1);
C{2} = B(A==2);
C{3} = B(A==3);
In reality, A contains all integers from 1 to 1600 (monotonically increasing, but each integer appears a different number of times), so it is impractical to write all lines out. So far, I have solved this with a loop (in each iteration, I create the mask C = B(A==iteration)), but loops are inefficient, so are there better ways to do it?
Similarly, I want to use this to assign values to the elements of a vector v. For example:
v(1) = sum(M(C{1}));
v(2) = sum(M(C{2}));
Where M is some other large vector from which we select the relevant entries by the indices in C as indicated. Again, this is currently implemented as a loop (i.e. v(i) = sum(M(B(A==i))) ), which works, but again, are there better ways to do it?

Respuesta aceptada

Stephen23
Stephen23 el 13 de Dic. de 2021
Editada: Stephen23 el 13 de Dic. de 2021
A = [1,1,1,2,2,3,3,3,3];
B = [6,3,7,4,7,13,16,4,1];
C = accumarray(A(:),B(:),[],@(v){v});
C{:}
ans = 3×1
6 3 7
ans = 2×1
4 7
ans = 4×1
13 16 4 1
For the second part of your question I would skip the cell array entirely:
M = randi(9,1,20);
V = accumarray(A(:),M(B(:)),[],@sum)
V = 3×1
15 9 17
  2 comentarios
Dominik Rhiem
Dominik Rhiem el 14 de Dic. de 2021
Editada: Dominik Rhiem el 15 de Dic. de 2021
This is great, thank you. There is still one issue though: In one instance, I want to use accumarray to first take the logarithm of selected elements of a vector and then take the sum of those elements. However, some entries of that vector are 0, meaning after taking the logarithm they are at -Inf (we later take the exponential so that the result is 0 again). This was fine in the 'loop version' because Log would simply return -Inf (meaning after the sum and taking the exponential, we end up with 0 again), however, with accumarray, I get the following error: The function 'log' returned a non-scalar value. How can I solve this issue?
edit: Nevermind, I got it. First took the log of the whole thing and then the sum of the selected elements.
Dominik Rhiem
Dominik Rhiem el 21 de Dic. de 2021
Hi, if you don't mind, I have a follow-up question. What if M and v are now matrices, not vectors, where I want to do the operation described above column-wise? I.e.:
v(:,1) = accumarray(A(:), v(B(:),1), [], @sum);
v(:,2) = accumarray(A(:), v(B(:),2), [], @sum);
Again, currently, I solved this with a loop, but more efficiency would be nice.

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Matrices and Arrays en Help Center y File Exchange.

Etiquetas

Productos


Versión

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by