How to set bottom repeating elements in matrix to NaN?

I have matrix of large size and I need to change the bottom repeating elements to nan. For instance:
a = [ 1 2 3 2 1 3
3 1 1 3 1 2
1 2 3 3 2 1
1 2 1 2 1 3
1 2 3 1 2 1];
In this matrix, I want to change the bottom repeating numbers. If the numbers are repeating on top, I don't want to do anything to them. Just want to replace the bottom repeating number by NaNs. Any help will be greatly appreciated.
Thank you.

7 Kommentare

Edited as per a comment
a=[1 2 3 2 1 3
3 1 1 3 1 2
1 2 3 3 2 1
1 2 1 2 1 3
1 2 3 1 2 1];
for j=1:2
for i=2:size(a,1)
if any(a(1:i-1,j)==a(i,j))
a(i,j)=NaN;
end
end
end
a
a = 5×6
1 2 3 2 1 3 3 1 1 3 1 2 NaN NaN 3 3 2 1 NaN NaN 1 2 1 3 NaN NaN 3 1 2 1
Please show complete example. Please define what a "bottom repeating number" is. What is the desired outcome for the matrix you show?
Bottom repeating numbers are in block letter. 1 and 2 in first two columns. sorry for the inconvenience.
The desire outcomes of the matrix should be
a = [ 1 2 3 2 1 3
3 1 1 3 1 2
NaN NaN 3 3 2 1
NaN NaN 1 2 1 3
NaN NaN 3 1 2 1];
Sushil Pokharel
Sushil Pokharel am 16 Jun. 2022
Verschoben: Dyuman Joshi am 26 Aug. 2023
It won't work for general case. for instance: if I choose a different matrix then I will get wrong answer.
a=[1 2 3 2 1 3
3 1 1 3 1 2
1 2 3 3 2 1
1 2 1 2 1 3
1 2 3 1 2 1
3 2 1 1 2 1];
ans: a =
1 2 3 2 1 3
3 1 1 3 1 2
NaN NaN 3 3 2 1
NaN NaN 1 2 1 3
NaN NaN 3 1 2 1
NaN NaN 1 1 2 1
but the real answer should be something like this:
a =
1 2 3 2 1 3
3 1 1 3 1 2
1 NaN 3 3 2 1
1 NaN 1 2 1 3
1 NaN 3 NaN NaN NaN
3 NaN 1 NaN NaN NaN
Anyway, I really appreciate your attempt. Thank you so much. Also, I already accepted @Voss answer which is working fine.
Dyuman Joshi
Dyuman Joshi am 16 Jun. 2022
Verschoben: Dyuman Joshi am 26 Aug. 2023
Okay. Just a note - If you want a general answer, do mention information explicitly. Answers will always be tailored according to the information you give. So limited data results in particular answer rather than a general solution.
I could only understand what you want to obtain after you gave another example above. Nonetheless, you got your answer.
Sushil Pokharel
Sushil Pokharel am 16 Jun. 2022
Verschoben: Dyuman Joshi am 26 Aug. 2023
@Dyuman Joshi you are absolutely right. Sorry for the inconvenience.

Melden Sie sich an, um zu kommentieren.

 Akzeptierte Antwort

a = [ 1 2 3 2 1 3
3 1 1 3 1 2
1 2 3 3 2 1
1 2 1 2 1 3
1 2 3 1 2 1];
to_nan = cummin(a(1:end-1,:) == a(end,:),1,'reverse');
to_nan = to_nan([1:end end],:);
a(to_nan) = NaN
a = 5×6
1 2 3 2 1 3 3 1 1 3 1 2 NaN NaN 3 3 2 1 NaN NaN 1 2 1 3 NaN NaN 3 1 2 1

4 Kommentare

Thank you so much @Voss. I really appreciate your valuable time and help.
But I am kind of not getting what is the thing happening in the second line.
to_nan = cummin(a(1:end-1,:) == a(end,:),1,'reverse');
It would be really helpful if you can give little explanation about this line.
cummin is cumulative minimum. The second argument 1 tells it to operate in an up/down direction and 'reverse' tells it to go up from the bottom. So start at the bottom of the matrix and keep track of the running minimum value in each column. For example:
A = magic(5)
A = 5×5
17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9
cummin(A,1,'reverse')
ans = 5×5
4 5 1 2 3 4 5 7 2 3 4 6 13 2 3 10 12 19 2 3 11 18 25 2 9
So it's the smallest value encountered in each column of A as you start at the bottom and move up.
Now, I'm doing that on a logical matrix that says whether each element of the last row of your a is equal to the element of each other other row (in the same column):
a = [ 1 2 3 2 1 3
3 1 1 3 1 2
1 2 3 3 2 1
1 2 1 2 1 3
1 2 3 1 2 1]
a = 5×6
1 2 3 2 1 3 3 1 1 3 1 2 1 2 3 3 2 1 1 2 1 2 1 3 1 2 3 1 2 1
a(1:end-1,:) == a(end,:)
ans = 4×6 logical array
1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0
Imagine starting at the bottom of that matrix and going up, keeping track of the minimum value encountered so far in each column as you go up. As soon as you hit a zero, you'll get zeros the whole rest of the way, since there's not going to be anything less than that.
cummin(a(1:end-1,:) == a(end,:),1,'reverse')
ans = 4×6 logical array
0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0
And if you have a one in the output, it means you haven't hit a zero yet (i.e., it's ones all the way down).
When the cumulative minimum, going up from the bottom like that, is one, that means that the element there is equal to the element at the bottom of the column (since the cumulative minimum is of the comparison of rows of a, and where they are not equal, the value of a(1:end-1,:) == a(end,:) would be 0, which is less than 1). On the other hand, when the cumulative minimum is zero, that means that the element there is not equal to the element at the bottom of the column.
Therefore, the matrix above tells you where you have elements equal to and contiguous with the element at the bottoms of their respective columns.
Note that I'm using a(1:end-1,:), and not a(1:end,:) - which is just a - in the comparison. That is, I'm not comparing the last row to itself, because that would be like considering all values in the last row of a to be repeats (i.e., repeated once), which you wanted to avoid. So cummin(a(1:end-1,:) == a(end,:),1,'reverse') has one fewer row than a does, so to get the right result I append the last row of it to the end in the next line:
to_nan = to_nan([1:end end],:);
and use that to logical index into a to set those locations to NaN:
a(to_nan) = NaN
hi @Voss, I really appreciate your help. now I have clear understanding about the code. Thank you so much for your help.
You're welcome!

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Produkte

Version

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by