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

3 次查看(过去 30 天)
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.

采纳的回答

Stephen23
Stephen23 2018-6-28
编辑:Stephen23 2018-6-28
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 个评论
Stephen23
Stephen23 2018-7-6
编辑:Stephen23 2018-7-6
@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

请先登录,再进行评论。

更多回答(1 个)

Mandeep  Singh
Mandeep Singh 2018-6-28
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 个评论
Mantas Vaitonis
Mantas Vaitonis 2018-6-28
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 2018-6-28
编辑:Stephen23 2018-6-28
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

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Mathematics 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by