FInding value that satisfies 2 conditions

111 views (last 30 days)
Mich
Mich on 19 Oct 2014
Commented: Star Strider on 26 Oct 2014
i need to verify the accuracy of the different measuring systems (data stored in diff .mat files) i'd used in my project by verifying it with the benchmark values. the different periods of measurement is stored in a step graph of 7 different steps. i opened the .mat file and realised that the values within are
"1 1 1 ..., 2 2 2..., 3 3 3 ..., 4 4 4 .., 5 5 5 ...., 6.....,7...., 1....., 2...."
There are a total of 5040 cycles of 1..,2......till 7.
I've managed to come up with a code to determine the first value of every set of values i.e.the index where the first '3' is detected, first '2'...
idx= (find(diff(RuleState)==1));
idx(end+1) = 0;
idx = idx([end, 1:end-1]);
idx = idx + 1;
However, I realised that by doing so, I'll be leaving out the start of the '1's as the difference between the first '1' and the previous value '7' is 6. so I tried to include an OR condition to the first line. But the code doesnt work.
idx= (find(diff(RuleState)==1)) | (find(diff(RuleSTate)==6));
idx(end+1) = 0;
idx = idx([end, 1:end-1]);
idx = idx + 1;
Can I have some help regarding this as I cant find anything online. Thanks!!

Answers (3)

dpb
dpb on 19 Oct 2014
idx= (find(diff(RuleState)==1)) | (find(diff(RuleSTate)==6));
You're or'ing the result of find which is the numeric location(s) where the condition is true. or(32,12) say isn't a useful logical operation. or the condition, and then find the locations (or just use the resulting logical addressing array).
idx= find((diff(RuleState)==1) | (diff(RuleSTate)==6));
  3 Comments
dpb
dpb on 20 Oct 2014
There's no retrieving a clear ed variable unless you had saved workspace or it. You can look at the history and retrieve the set of operations done if at the command line that previously generated it, however.
But, instead of that, explain again more fully what you're actually looking for--is it the first location of each group of the set of integers 1:7 sequentially or are there multiple sets wanted at a time?
Mich
Mich on 22 Oct 2014
Im actually working to analyse the different systems used to measure the walking gait phases. I've attached an image of the data i'm working with. Each number on the y-axis represent a different gait phase, while each set of steps represent 1 gait cycle. I'm trying to compare if the 2 other systems used (red and green) coincide with the benchmark (black).
So, I'm trying to obtain the start of each 'step' i.e. the first value of every set of similar numbers, and compare. I've currently managed to obtain the index of every first value except for the number 1. This is because the difference between '1' and the value before, which is 7, is not 1.
However, I've realised that using the diff () function will give me a 1 or 0 depending on whether the value at the particular index satisfies the condition that I'm looking for. Thus, I've changed to use a 'for loop' instead.
for i = 1: length(RuleState)
if RuleState(i,1) == 1 && (RuleState((i-1),1)- RuleState(i,1) ==1)
idx_b(i) = i;
end
end
However, I'm not able to obtain the matrix idx_b as I've deleted it by accident.

Sign in to comment.


Star Strider
Star Strider on 20 Oct 2014
The easiest way to test for the transitions would likely to be with the filter function (although conv could also work):
vt = 1:7; % Create Data
mt = repmat(vt,4,5); % Create Data
v = mt(:)'; % Vector Of Serial Repeats
vr = filter([7 1]/14,1,v); % Use Pattern To Find Transitions
vi = [1 find((vr > 1-1E-5) & (vr < 1+1E-5))]; % Find ‘vr’ = 1
vm = [[1:length(v)]' v' vr']; % Check Data To Verify Result (Discard)
This simply filters the vector ‘v’ with the serial repeats for the occurrence of the [7 1] pattern (creating vector ‘vr’). It then checks ‘vr’ for values approximating 1 (allowing for the errors inherent in digital computations). It then uses the find function to locate all the first indices of 1 values, reporting them in ‘vi’. The ‘vm’ matrix simply shows the result, with the index numbers in the first column, the data vector in the second, and the output of the filter in the third.
Note that this code creates everything as row vectors, so do the appropriate transposes if your data are column vectors.
  4 Comments
Mich
Mich on 26 Oct 2014
hey thanks for your help! finally got it, will be using this for another part of my code instead, thanks! :)

Sign in to comment.


dpb
dpb on 20 Oct 2014
Edited: dpb on 20 Oct 2014
Assuming I do understand what you're looking for, look at the following--
I took your above vector and augmented it just a little for working case
>> v=[1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 7 1 2 2 3 3 3 4 4 4 5 5 5 6 7];
>> ixgrp=diff([0 v])~=0; % each breakpoint location
>> [v;ixgrp;ixgrp & v==1] % find each starting point of "1" in v
ans =
Columns 1 through 21
1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 7 1 2 2 3
1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 1 1 1 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
Columns 22 through 31
3 3 4 4 4 5 5 5 6 7
0 0 1 0 0 1 0 0 1 1
0 0 0 0 0 0 0 0 0 0
For each set simply change the value looked for in the original vector in sequence.
NB that often as here the "trick" in the end effects with diff is to augment the initial vector appropriately so the result is still the same length as the undifferentiated vector. Adding the preceding '0' since it's known the initial value is nonzero makes the first location easy regardless of it's actual value.
  3 Comments
dpb
dpb on 22 Oct 2014
diff ([0 v]) is simply augmenting (by prepending) the results of diff(v) with a zero so the length of the resulting vector of differences is the same as the vector. For the "trick" to work, to locate the first element as a transition the prepended value must be one other than the first value in the set of values. I chose zero because it's not a member of your vector.
What actually finds the various levels is the last line in the displayed array of and ing the logic vector of transitions with the logic vector of v==N (where N==1 in the example; to find the beginning of the sequence of fives, write
idx5=(ixgrp & v==5);
As noted, to find each in sequence you can write a loop--
ixgrp=diff([0 v])~=0;
u=unique(v); % the unique values in v
for i=1:length(u)
idN=(ixgrp & v==u(i));
% do whatever w/ that group here
...
Mich
Mich on 26 Oct 2014
hey thanks! tried out the code and it's good for me :)

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!