FInding value that satisfies 2 conditions

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!!

Réponses (3)

dpb
dpb le 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 commentaires

I tried your suggestion, but the code still doesnt detect the index where the first '1' appears after the number '7'.
So i tried to put them in a for and if loop. However, my Matlab program is unable to detect the variable idx_b as I had accidentally deleted the variable from the workspace. Can I check if there is any way I can recover the variable? I tried changing the name of the variable but it still doesnt work.
for i = 1: length(RuleState)
if (diff(RuleState)==1) | (diff(RuleState)==6);
idx_b(i) = i;
idx_b(end+1) = 0;
idx_b(i) = idx_b([end, 1:end-1]);
idx_b(i) = idx_b(i) + 1;
end
end
dpb
dpb le 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?
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.

Connectez-vous pour commenter.

Star Strider
Star Strider le 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 commentaires

Mich
Mich le 22 Oct 2014
thanks! this is quite a useful method. but, i dont quite understand why is the adaptive filter used [7 1]/14 instead of 7 1 alone.
Star Strider
Star Strider le 22 Oct 2014
My pleasure!
The 14 in the denominator comes from the filter multiplying (1*7+7*1) in its filtering. Dividing by 14 makes it easier to identify the transitions (that are then all 1) because only the [7 1] transitions will result in a value of 14. (It is easier to detect them visually if they are normalised to 1. That makes it easier to check to be sure the code is working and that only the transitions result in a specific value.)
It isn’t necessary to divide by 14, but if you decide not to, you simply have to test for 14 in the filter output rather than testing for 1. It should work regardless in your application. You will need to retain the limits in the ‘vi’ assignment to account for floating-point approximation errors.
I use the filter approach when I’m searching for specific patterns in data, such as your [7 1] transitions. It’s easier than using convolution, and reliable.
Mich
Mich le 26 Oct 2014
hey thanks for your help! finally got it, will be using this for another part of my code instead, thanks! :)
Star Strider
Star Strider le 26 Oct 2014
My pleasure!

Connectez-vous pour commenter.

dpb
dpb le 20 Oct 2014
Modifié(e) : dpb le 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 commentaires

Mich
Mich le 22 Oct 2014
thanks! this is what i'm trying to do!
Just to clarify some doubts: I dont quite understand how diff ([0 v]) works. Based on my understanding, I understand that diff() will find the difference between the 0 and the values within v. Thus, i'm not very clear as to why this can find all the breakpoints other than the value '1'.
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 le 26 Oct 2014
hey thanks! tried out the code and it's good for me :)

Connectez-vous pour commenter.

Catégories

En savoir plus sur Function Creation dans Centre d'aide et File Exchange

Question posée :

le 19 Oct 2014

Commenté :

le 26 Oct 2014

Community Treasure Hunt

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

Start Hunting!

Translated by