Selecting min value per row unless min value is repeated in another row.

Hi, I have a matrix of values shown below. I want to keep the lower value in each row, unless that lower value is repeated in another row of the matrix. For the matrix shown below, the retained values should be 7, 9, 14, 22, 24, 27, 29, 35, 30, 34, 38, and 44. My first thought was the unique function, but that then prevents me from selecting the min value per row. Thanks in advance for the help.
A = [1 2
1 3
2 3
5 6
3 7
2 8
3 8
8 9
5 10
6 10
10 12
11 13
12 15
11 16
13 16
15 20
14 21
22 28
24 31
20 32
27 33
29 34
32 35
30 36
34 42
38 43
40 48
40 49
48 49
44 50];

 Respuesta aceptada

Stephen23
Stephen23 el 24 de En. de 2020
Editada: Stephen23 el 24 de En. de 2020
Set the duplicate values to Inf/NaN, take the minimum of each row, then remove the Inf/NaN values:
>> A = [1,2;1,3;2,3;5,6;3,7;2,8;3,8;8,9;5,10;6,10;10,12;11,13;12,15;11,16;13,16;15,20;14,21;22,28;24,31;20,32;27,33;29,34;32,35;30,36;34,42;38,43;40,48;40,49;48,49;44,50];
>> U = unique(A(:));
>> A(ismember(A,U(histc(A(:),U)>1))) = Inf; % duplicate values -> Inf.
>> V = min(A,[],2);
>> V = V(isfinite(V)) % remove Inf.
V =
7
9
14
22
24
27
29
35
30
42
38
44
This differs from your example output (which contains 34 instead of 42, even though 34 occurs twice).

4 comentarios

Vance Blake
Vance Blake el 24 de En. de 2020
Editada: Vance Blake el 24 de En. de 2020
As soon as I posted the question, I saw that I inculded the wrong number lol. But thank you for the solution. If I'm understanding your code properly, you use unique to remove the duplicates. Then you compare A to U using ismember and while accounting for any repeated numbers in A using histc/histcounts to separate them and then replace the repeated numbers in A with Inf. After that you use the second dimension of the min function to select the lower value in each row, and store them in V. And then finally remove the Inf values from V since some rows will both be Inf with isfinite(). And If I wanted to use NaN then I would replace Inf and use isnan() instead. Thanks again Stephen.
If I wanted to include the right bin edge how would I modify the histcounts function using 'edges'? I have numbers that range from 1 to 50, but 50 keeps being ignored currently if it occurs in 2 separate rows.
Reading the histc and histcounts documentation it is clear that unfortunately histcounts treats the right edge of the last bin very differently to histc, namely:
  • histc: "The last bin consists of the scalar value equal to last value in binranges."
  • histcounts: "The last bin also includes the right bin edge..."
So the solution is to define the last bin's right edge as not equal to any of your data, e.g. Inf:
>> A = [1,2;1,3;2,3;5,6;3,7;2,8;3,8;8,9;5,10;6,50;50,12]
A =
1 2
1 3
2 3
5 6
3 7
2 8
3 8
8 9
5 10
6 50
50 12
>> U = [unique(A(:));Inf]; % force last bin to only include last unique value
>> A(ismember(A,U(histcounts(A(:),U)>1))) = NaN; % duplicate values -> NaN.
>> V = min(A,[],2);
>> V = V(isfinite(V)) % remove NaN.
V =
7
9
10
12
Okay I see what you mean. Thank you for clearing that up. Just wondering but why does Mathworks not recommend histc then?? It seems like the legacy fucntion is more useful than histcounts.

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Productos

Versión

R2019a

Preguntada:

el 24 de En. de 2020

Comentada:

el 25 de En. de 2020

Community Treasure Hunt

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

Start Hunting!

Translated by