How to use firs value from array column when threshold is reached without for loop?

Hello Everyone,
I have the following problem I am trying to solve. The situation is like this, if we look at the column there can’t be two numbers in a row that are above or below predefined threshold value. For example if we have array D:
D=-2 2 3 -1 -5
1 4 -2 3 4
5 3 -4 6 -5
-7 -2 1 4 -1
And we use threshold 0, then it should fulfill this logic
If D>0
B=D
And other values of B are zeros till D<0, then
B=D;
And other values of B are zeros till D>0, and so on.
As in our example final result should look like this:
B=0 2 3 0 0
1 0 -2 3 4
0 0 0 0 -5
-7 -2 1 0 0
The idea is to track when the threshold value is crossed and keep the values of D when threshold was crossed, the result matrix would be used for further calculations. Maybe someone would have an idea how to do this. In reality I would be using big arrays like 100000x20000, thus would be great to avoid for loops.

 Akzeptierte Antwort

Stephen23
Stephen23 am 28 Jun. 2018
Bearbeitet: Stephen23 am 28 Jun. 2018
This actually returns the requested matrix, and follows the description in the question:
>> thr = 0;
>> D = [-2,2,3,-1,-5;1,4,-2,3,4;5,3,-4,6,-5;-7,-2,1,4,-1]
D =
-2 2 3 -1 -5
1 4 -2 3 4
5 3 -4 6 -5
-7 -2 1 4 -1
>> X = D>thr;
>> Y = D<thr & cumsum(X)>0;
>> Z = [X(1,:); diff(X)>0 | diff(Y)>0];
>> B = zeros(size(D));
>> B(Z) = D(Z)
B =
0 2 3 0 0
1 0 -2 3 4
0 0 0 0 -5
-7 -2 1 0 0
Compared to the requested output matrix:
>> [0 2 3 0 0; 1 0 -2 3 4; 0 0 0 0 -5; -7 -2 1 0 0]
ans =
0 2 3 0 0
1 0 -2 3 4
0 0 0 0 -5
-7 -2 1 0 0

6 Kommentare

Stephen Cobeldick, thanks for Your comment and you notice of problem. I saw this bug, and was able to solve it, by first taking care of first row. However your code is more elegant, and compered to my fixed method it was about 15% faster when working with big arrays.
@Stephen Cobeldick, maybe you could help a bit more with your code? Because if there a zero values in array, the code does not work.
D = [2,2,2,-1,-5;0,4,-2,3,4;0,3,0,6,-5;2,-2,0,4,-1;2,-2,-1,4,-1]
Then result B is
B =
2 2 2 0 0
0 0 -2 3 4
0 0 0 0 -5
2 -2 0 0 0
0 0 -1 0 0
As you can see first and third column have same values, not change by threshold.
Stephen23
Stephen23 am 6 Jul. 2018
Bearbeitet: Stephen23 am 6 Jul. 2018
@Mantas Vaitonis: Please please please always provide an output example. Showing an incorrect output is fine, but you also need to show what the correct output is, otherwise I have nothing to check my code against.
@Stephen Cobeldick, sorry for not providing with enough information, the output B should look like this:
B =
2 2 2 0 0
0 0-2 3 4
0 0 0 0-5
0-2 0 0 0
0 0 0 0 0
@Mantas Vaitonis: you are right, it is required to keep track of the previous state of the elements whose values are equal to thr. Using a loop is one way to achieve that:
thr = 0
D = [2,2,2,-1,-5;0,4,-2,3,4;0,3,0,6,-5;2,-2,0,4,-1;2,-2,-1,4,-1]
Z = D(1,:)>thr;
B = zeros(size(D));
B(1,Z) = D(1,Z);
for k = 2:size(B,1)
X = D(k,:)<thr & Z;
Y = D(k,:)>thr & ~Z;
B(k,X|Y) = D(k,X|Y);
Z(X) = false;
Z(Y) = true;
end
giving:
B =
2 2 2 0 0
0 0 -2 3 4
0 0 0 0 -5
0 -2 0 0 0
0 0 0 0 0
@Stephen Cobeldick thank you for the answer and your time.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Refer to the following snippet of code for the desired result. The code avoids any for loops and gives out the result.
D=[2 2 3 -1 -5;
1 4 -2 3 4;
5 3 -4 6 -5;
-7 -2 1 4 -1];
d = D(:);
consec = logical(abs( (d(2:end)>0) - (d(1:end-1)>0) )); %Change threshold if required from here
B = zeros(size(d));
B([D(1)>0; consec]) = d([D(1)>0; consec]);
B = reshape(B, size(D,1), size(D,2))

2 Kommentare

Oh, Thank You. Sometimes it looks like magic, how fast you respond with the answer. It took me 5 days with no result, and only couple hours for you :) It took me some time to go through your code and it seems it does what I need.
This answer is buggy and does not return the requested output:
B =
0 2 3 -1 -5 % -1 and 5 should both be 0
1 0 -2 3 4
0 0 0 0 -5
-7 -2 1 0 0
The bug is due to the conversion of D into a column vector. By putting all of the data into one column vector d, it treats all elements D(1,2:end) as following elements D(end,1:end-1), thus leading to the incorrect values shown. It might be possible to fix but this would just make this code more complex.
See my answer for a simple solution that actually returns the requested output matrix:
0 2 3 0 0
1 0 -2 3 4
0 0 0 0 -5
-7 -2 1 0 0

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Loops and Conditional Statements finden Sie in Hilfe-Center und File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by