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

2 vues (au cours des 30 derniers jours)
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.

Réponse acceptée

Stephen23
Stephen23 le 28 Juin 2018
Modifié(e) : Stephen23 le 28 Juin 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 commentaires
Stephen23
Stephen23 le 6 Juil 2018
Modifié(e) : Stephen23 le 6 Juil 2018
@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
Mantas Vaitonis
Mantas Vaitonis le 6 Juil 2018
@Stephen Cobeldick thank you for the answer and your time.

Connectez-vous pour commenter.

Plus de réponses (1)

Mandeep  Singh
Mandeep Singh le 28 Juin 2018
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 commentaires
Mantas Vaitonis
Mantas Vaitonis le 28 Juin 2018
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.
Stephen23
Stephen23 le 28 Juin 2018
Modifié(e) : Stephen23 le 28 Juin 2018
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

Connectez-vous pour commenter.

Catégories

En savoir plus sur Performance and Memory dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by