Identify, for each column of a matrix, numbers that are smaller than the previous ones, creating a 0 1 output having the same size of the original matrix

Dear all,
I've got a matrix, let's call it M.
M = 1000x1200
The first 3 columns of M look like:
1.05 21.22 17.2 ...
2.01 22.35 18.2 ...
3.52 23.63 19.2 ...
4.32 23.54 20.2 ...
5.11 23.56 18.2 ...
6.89 23.64 19.2 ...
7.01 23.65 20.3 ...
8.87 23.99 21.3 ...
6.52 24.52 22.3 ...
7.91 24.51 23.3 ...
8.42 24.515 24.3 ...
9.03 24.525 22.3 ...
10.88 25.23 24.4 ...
11.01 45.12 25.4 ...
11.32 48.13 24.4 ...
11.33 46.14 26.4 ...
12.12 46.15 31.1 ...
12.09 48.142 32.2 ...
12.11 48.143 30.02 ...
12.13 48.151 31.6 ...
12.52 48.36 33.1 ...
Now, what I am trying to do is to loop through each column of M, from column 1 to column 1200, and identify all of the numbers that are smaller than the last, greater, number of a sequence. From this loop I'm trying to obtain a matrix, let's call it Mx of the same size of M, made of 0 and 1, where 1s denote the numbers that are smaller than the preavious ones.
For the example above, Mx would be:
0 0 0 ...
0 0 0 ...
0 0 0 ...
0 1 0 ...
0 1 1 ...
0 0 1 ...
0 0 1 ...
0 0 0 ...
1 0 0 ...
1 1 0 ...
1 1 0 ...
0 0 1 ...
0 0 0 ...
0 0 0 ...
0 0 1 ...
0 1 0 ...
0 1 0 ...
1 1 0 ...
1 0 1 ...
0 0 1 ...
0 0 1 ...
Any help would be massively appreciated!

2 Commenti

To confirm that I understand correctly:
You go down each column, keeping a running maximum-seen-so-far. For each entry that is less than the maximum seen so far in the column, a 1 should be emitted, and 0 for values that are new maxima ?
To confirm, if you encounter a value that is equal to the maximum seen so far, then because equal is not "less than", 0 should be emitted for the duplicate ?
* EDIT: Attached a sample of my dataset.*
Hi @Walter Roberson, it's me again. Altought the code runs brilliantly, I encountered a situation which i did not considered in my original question.
The previous code correctly identifies all of the values less than the maximum seen so far. The figure below shows colum 1 of my matrix with red circles indicating the values more than the minimum seen so far (namely the values identified with 1s):
However, I encountered a situation where values are not more than the minimum seen so far, but deviate from a linear trend, or better say "make some steps":
These are not considered in the script you kindly suggested.
I wonder if these deviations from the linear trend could also be identified as 1s?
I have included a sample of my actual dataset.
Thank a lot!

Accedi per commentare.

Risposte (1)

My output is a bit different from yours, but I think I followed the algorithm you wanted.
M = [ ...
1.05 21.22 17.2; ...
2.01 22.35 18.2; ...
3.52 23.63 19.2; ...
4.32 23.54 20.2; ...
5.11 23.56 18.2; ...
6.89 23.64 19.2; ...
7.01 23.65 20.3; ...
8.87 23.99 21.3; ...
6.52 24.52 22.3; ...
7.91 24.51 23.3; ...
8.42 24.515 24.3; ...
9.03 24.525 22.3; ...
10.88 25.23 24.4; ...
11.01 45.12 25.4; ...
11.32 48.13 24.4; ...
11.33 46.14 26.4; ...
12.12 46.15 31.1; ...
12.09 48.142 32.2; ...
12.11 48.143 30.02; ...
12.13 48.151 31.6; ...
12.52 48.36 33.1]; ...
nrows = height(M);
Mx = zeros(size(M));
for nr = 2:nrows
Mx(nr,:) = M(nr,:) < max(M(1:nr,:));
end
Mx
Mx = 21×3
0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 1 0 0 0 0 0 0 1 0 0 1 1 0

8 Commenti

Different implementation that should be more efficient.
M = [ ...
1.05 21.22 17.2; ...
2.01 22.35 18.2; ...
3.52 23.63 19.2; ...
4.32 23.54 20.2; ...
5.11 23.56 18.2; ...
6.89 23.64 19.2; ...
7.01 23.65 20.3; ...
8.87 23.99 21.3; ...
6.52 24.52 22.3; ...
7.91 24.51 23.3; ...
8.42 24.515 24.3; ...
9.03 24.525 22.3; ...
10.88 25.23 24.4; ...
11.01 45.12 25.4; ...
11.32 48.13 24.4; ...
11.33 46.14 26.4; ...
12.12 46.15 31.1; ...
12.09 48.142 32.2; ...
12.11 48.143 30.02; ...
12.13 48.151 31.6; ...
12.52 48.36 33.1]; ...
nrows = height(M);
Mx = zeros(size(M));
runningmax = M(1,:);
for nr = 2:nrows
runningmax = max(runningmax, M(nr, :));
Mx(nr,:) = M(nr,:) < runningmax;
end
Mx
Mx = 21×3
0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 1 0 0 0 0 0 0 1 0 0 1 1 0
EDIT: I believe I realised why it didn't work. I changed max with min and < with >. That works great now!
Thank you very much for your timely reply. I have tried the code you kindly suggested, but it didn't work on my dataset. The output is a matrix of the correct size, but all columns are made of 1s, except for the first row, which is 0s. Please note, i changed < with > as the actual dataset is made of decresing values.
Also, there should be no situation where 2 numbers are the same, however, in that scenario, the second number should be considered as "1".
Thanks a lot once again!
Sorry, I thought an actual sample of the dataset would have been more helpful. The code Walter proposed above seemed to work fine with that dataset, but not with the actual one. That's why I have tried to provide more information. Yet, I understand your point. Sorry, once again.
[EDIT: I see that you figured it out.]
@Simone A.: You say, "i changed < with > as the actual dataset is decresing", but did you also change max to min?
% this mat-file contains your example input and output:
S = load('result.mat')
S = struct with fields:
M: [100×3 double] Mx: [100×3 double]
M = S.M
M = 100×3
47.3217 47.3217 47.3217 47.3205 47.3205 47.3206 47.3180 47.3180 47.3181 47.3138 47.3138 47.3139 47.3086 47.3086 47.3087 47.3032 47.3033 47.3033 47.2984 47.2985 47.2985 47.2938 47.2938 47.2938 47.2891 47.2891 47.2892 47.2844 47.2844 47.2845
nrows = size(M,1);
Mx = zeros(size(M));
for nr = 2:nrows
Mx(nr,:) = M(nr,:) > min(M(1:nr,:));
end
% it works:
isequal(Mx,S.Mx)
ans = logical
1
Suppose your input was just the first two rows of your actual dataset.
M = [47.3216588841751 47.3216800214723 47.3217246586864;
47.3204898359254 47.3205112712458 47.3205565517710];
Why is the correct output
[0 0 0;
0 0 0]
rather than
[0 0 0;
1 1 1]
?
Each element in the second row is smaller than the element above it, so aren't we supposed to label that "1"? It looks like every column is uniformly decreasing in your full dataset, so your description suggests everything should be 1's.
"however, in that scenario, the second number should be considered as "1"."
That takes more code
M = [ ...
1.05 21.22 17.2; ...
2.01 22.35 18.2; ...
3.52 23.63 19.2; ...
4.32 23.54 20.2; ...
4.32 23.56 18.2; ... %identical
6.89 23.56 19.2; ... %identical
7.01 23.65 20.3; ...
8.87 23.99 21.3; ...
6.52 24.52 22.3; ...
7.91 24.51 23.3; ...
8.42 24.515 24.3; ...
9.03 24.525 22.3; ...
10.88 25.23 24.4; ...
11.01 45.12 25.4; ...
11.32 48.13 24.4; ...
11.33 46.14 26.4; ...
12.12 46.15 31.1; ...
12.09 48.142 32.2; ...
12.11 48.143 30.02; ...
12.13 48.151 31.6; ...
12.52 48.36 33.1]; ...
nrows = height(M);
Mx = zeros(size(M));
runningmax = M(1,:);
for nr = 2:nrows
oldrunningmax = runningmax;
runningmax = max(runningmax, M(nr, :));
Mx(nr,:) = M(nr,:) < runningmax | M(nr, :) == oldrunningmax;
end
Mx
Mx = 21×3
0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 1 1 0 0 0 0 0 0 1 0 0 1 1 0
This is absolutelly perfect! Thanks a lot for your help!

Accedi per commentare.

Prodotti

Release

R2022b

Richiesto:

il 13 Gen 2023

Modificato:

il 14 Gen 2023

Community Treasure Hunt

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

Start Hunting!

Translated by