count number values exceeds given threshold in moving window in matlab - matlab

I have time vs values plot. time =100. I want to select time 1 to 4 & then count how many values are exceeding 20. i.e. for time 1 to 4 values are 16 43 94 21 so 3 values are exceeding 20 so count should be 3. then want move window so time is 2 to 5 & count number of values exceeding 20. so last window would be 97 to 100. I tried following code but it showing 0 & 1
N=4;% length of window
d=length(t);% t has 100 values so took length
for e=0:d-N;
for x=1+e:N+e;
y(x)=sum(t(x)>20); % t contains values so took t(x)
end
end
how to do it.

You can use a logical index showing where t is greater than 20 then use movsum to count how many values in sliding window exceed 20;
N =4;
idx = t > 20;
result = movsum(idx,N)

Related

Using IF loop and monotonic data in Matlab

I am trying to select specific data within a time vector to assign a specific start point.
Vit_lim = 5*(max(dcursor))/100
A = find(dcursor > Vit_lim)
A = [1 2 3 4 5 6 7 8 158 159 160.........318]
The start point is being dectected as first value.
The initial 8 values are a false positive (and do not represent real start point (158).
I need to add a condition that finds start point if first value increases monotonically for 20 consecutive values.
This is within a larger loop.
So,
A = [1 2 3 4 5 6 7 8 158 159 160.........318]
found=0;
idx=1;
monoticSum=0;
tempValue=A(1);
idx=2;
While found == 0
temp=A(idx);
if ((tempValue+1) == temp)
monoticSum = monoticSum+1;
tempValue = temp;
else
monoticSum = 0
end
if (monoticSum == 20)
found=1;
break
end
idx=idx+1
end
This should work.
Actually, this is a nice starting point. But you need to restart the variable monoticSum if you find any transition less than 20. I've updated.
I'm not sure what you mean by 20 consecutive values, given that your sample data has 8 false-start values. But here's an idea that finds a sample that's at least 20 away from the previous
b=find(diff(A)>20);
start_idx = A(b+1);

Matlab: Count till sum equals 360 > insert event1, next 360 >insert event 2 etc

I have been trying to solve this problem for a while now and I would appreciate a push in the right direction.
I have a matrix called Turn. This matrix contains 1 column of data, somewhere between 10000 and 15000 rows (is variable). What I like to do is as follows:
start at row 1 and add values of row 2, row 3 etc till sum==360. When sum==360 insert in column 2 at that specific row 'event 1'.
Start counting at the next row (after 'event 1') till sum==360. When sum==360 insert in column 2 at that specific row 'event 2'. etc
So I basically want to group my data in partitions of sum==360
these will be called events.
The row number at which sum==360 is important to me as well (every row is a time point so it will tells me the duration of an event). I want to put those row numbers in a new matrix in which on row 1: rownr event 1 happened, row 2: rownr event 2 happened etc.
You can find the row indices where events occur using the following code. Basically you're going to use the modulo operator to find where the sum of the first column of Turn is a multiple of 360.
mod360 = mod(cumsum(Turn(:,1)),360);
eventInds = find(mod360 == 0);
You could then loop over eventInds to place whatever values you'd like in the appropriate rows in the second column of Turn.
I don't think you'll be able to place the string 'event 1' in the column though as a string array is acts like a vector and will result in a dimension mismatch. You could just store the numerical value 1 for the first event and 2 for the second event and so on.
Ryan's answer looks like the way to go. But if your condition is such that you need to find row numbers where the cumulative sum is not exactly 360, then you would be required to do a little more work. For that case, you may use this -
Try this vectorized (and no loops) code to get the row IDs where the 360 grouping occurs -
threshold = 360;
cumsum_val = cumsum(Turn);
ind1 = find(cumsum_val>=threshold,1)
num_events = floor(cumsum_val(end)/threshold);
[x1,y1] = find(bsxfun(#gt,cumsum_val,threshold.*(1:num_events)));
[~,b,~] = unique(y1,'first');
row_nums = x1(b)
After that you can get the event data, like this -
event1 = Turn(1:row_nums(1));
event2 = Turn(row_nums(1)+1:row_nums(2));
event3 = Turn(row_nums(2)+1:row_nums(3));
...
event21 = Turn(row_nums(20)+1:row_nums(21));
...
eventN = Turn(row_nums(N-1)+1:row_nums(N));
Edit 1
Sample case:
We create a small data of 20 random integer numbers instead of 15000 as used for the original problem. Also, we are using a threshold of 30 instead of 360 to account for the small datasize.
Code
Turn = randi(10,[20 1]);
threshold = 30;
cumsum_val = cumsum(Turn);
ind1 = find(cumsum_val>=threshold,1)
num_events = floor(cumsum_val(end)/threshold);
[x1,y1] = find(bsxfun(#gt,cumsum_val,threshold.*(1:num_events)));
[~,b,~] = unique(y1,'first');
row_nums = x1(b);
Run
Turn =
7
6
3
4
5
3
9
2
3
2
3
5
4
10
5
2
10
10
5
2
threshold =
30
row_nums =
7
14
18
The run results shows the row_nums as 7, 14, 18, which mean that the second grouping starts with the 7th index in Turn, third grouping starts at 14th index and so on. Of course, you can append 1 at the beginning of row_nums to indicate that the first grouping starts at the 1st index.
Given a column vector x, say,
x = randi(100,10,1)
the following would give you the index of the first row where the cumulative sum off all the items above that row adds up to 360:
i = max( find( cumsum(x) <= 360) )
Then, you would have to use that index to find the next set of cumulative sums that add up to 360, something like
offset = max( find( cumsum(x(i+1:end)) <= 360 ) )
i_new = i + offset
You might need to add +1/-1 to the offset and the index.
>> x = randi(100,10,1)'
x =
90 47 47 44 8 79 45 9 91 6
>> cumsum(x)
ans =
90 137 184 228 236 315 360 369 460 466
>> i = max(find(cumsum(x)<=360))
i =
7

finding a position in loop can find the highest number but need its position

i have this code that i made it prints out "number" and the "value" where value is the order it came in which i obtained from a loop.
i was able to get the highest number from "numbers but can't find a way to print out its "VALUE" or which position its in for example:
number =
3 5 5 4
Value 1 has 3 number
Value 2 has 6 number
Value 3 has 5 number
Value 4 has 4 number
highest = 6
i want my out put to say
value 2 has 6 number
it can find 6 easily by using max(number) but how can i get its position in the loop?
and what is the case if we have 2 numbers equal could in say both the positions
this is my code
number
len= length(number);
%for aligning and display loop
x=1;
while x<=len
fprintf('Value %x has %d number \n',x,number(x))
x=x+1;
end
highest = max(number)
Try using,
[high, pos] = max(number);
instead of highest = max(number);
where high is the largest number and pos is the value you required.

Full range of values - matlab

I have got the following results after using [h, bins] = hist(H) in matlab:
h =
221 20 6 4 1 1 2 0 0 1
bins =
Columns 1 through 7
8.2500 24.7500 41.2500 57.7500 74.2500 90.7500 107.2500
Columns 8 through 10
123.7500 140.2500 156.7500
How do I know the full range of values? Especially that I expected to have up to 255, that is `[0,255], and if we analyze the range of the bins below we will have the following for the ten bins respectively:
0-16.5
16.5-33
33-49.5
49.5-66
66-82.5
82.5-99
99-115.5
115.5-132
132-148.5
148.5-165
So, did I get this range only due to having only 10 bins?
Thanks.
yes, the 10 bins are the default of hist. If you know you might have values between [0,255] you can force whatever bin positions you want, for example:
[h, bins] = hist(H,0:255)
will create 256 bins each for each integer value [0,255]

Full range of values on x-axis - matlab

I'm trying to check the full range of values on the x-axis of a histogram, especially while I expected the full range to be [0, 255], when I used the following command for the histogram [h, bins] = hist(H), I got the following:
h =
221 20 6 4 1 1 2 0 0 1
bins =
Columns 1 through 7
8.2500 24.7500 41.2500 57.7500 74.2500 90.7500 107.2500
Columns 8 through 10
123.7500 140.2500 156.7500
This implies that the maximum range I got here is up to 165.
If we look at the histogram below, we can see that 165 seems to be the maximum number of frequency value. How do I know the maximum value (range) of the x-axis?
I think you need either one of these 3 options:
max(H)
Or
numel(unique(H))
or
numel(H)
I would start at the top till you find the one you need.