How can I find adjacent identical values in a vector, flanked on either side by outliers?

9 views (last 30 days)
I am trying to find adjacent identical values in a vector, since they represent artifacts in heart rate data. So imagine 1Hz sample rate and we have a steadily climbing HR, then a stop, then it jumps to where it should be. I want to identify the suspect slope and the numbers before (and sometimes after) that value, so:
HR=[136 137 138 140 140 140 140 140 140 140 145 146 145 147]
according to certain literature, a slope over 2.6 bpm change/second is suspect, so I use diff...
a=diff(HR); %grabs the differences
b=a>2.6; %shows which ones are suspect
c=find(a==0); %shows where the slope is zero
and get
a =
1 1 2 0 0 0 0 0 0 5 1 -1 2
and
b =
0 0 0 0 0 0 0 0 0 1 0 0 0
and
c =
4 5 6 7 8 9
So the 10th element in the vector is my target, and the zero difference values (elements 4-9) in between are numbers that need to be replaced.
Is there some kind of way that I can use diff here? Is there a better solution?
Any thoughts would be welcome.
  4 Comments
Blake
Blake on 8 May 2015
We are not using waveform EKG, but rather instantaneous pulse rate. So something more like HR=[136 137 138 140 141 142 142 143 144 144 145 146 145 147]
where there is a gradual rise that does not violate the expected slope.
With respect to "numbers before (and sometimes after)", what I mean is that sometimes the series of identical adjacent values comes after a value greater than -2.6. So:
HR=[136 137 138 140 140 140 140 140 140 140 145 146 145 147 140 140 140 140 143 140 140 139];
In this case the questionable data is after the 147 point.
Blake
Blake on 8 May 2015
And also, it doesn't have to be diff... I am clutching at straws here and hoping for any decent solution.

Sign in to comment.

Accepted Answer

Joseph Cheng
Joseph Cheng on 8 May 2015
Edited: Joseph Cheng on 11 May 2015
Keep in mind the comments from the cyclist and Star Strider but to use diff you can do something like this.
HR=[136 137 138 140 140 140 140 140 140 140 145 146 160 137 138 143 143 143 143 143 143 143 145 146 145 147]
a = [diff(HR)]; %find difference
c = a==0|abs(a)>2.6; %find points that fit your criteria.
dc = diff(c);
rangec = [find(dc==1)'+1 find(dc==-1)'];
spointind = find(diff(rangec ,[],2)==1)
rjump = rangec(spointind,:);
rangec(spointind ,:)=[]
%where rangec is the index ranges by of [start finish] index per detected segment.
now some additional conditionals manipulations could be needed to specifically determine if my 'OR' of the two conditions meets everything you want and filtering for single point changes meets all possible conditionals. but its a place to start and i know i included the target index in my range but that can be extracted.
  2 Comments
Joseph Cheng
Joseph Cheng on 8 May 2015
no... i accidentally missed it when i decided to quickly modify rc to rangec after i pasted it into the answer window. I thought it was a good idea but i didn't have the time before my meeting to rerun my edits.
but step through what i was trying to do and you should see that i did mean rangec. as the spointind is looking for ranges that have a difference of 1. which means there was a instantaneous jump of 1 point. This is because 0 10 0 diffed is [10 -10] which after performing the conditional statements and finding start and finish of ranges would have an index difference of 1. so in that like i find the points where you don't have leading/following consecutive same values.
Blake
Blake on 8 May 2015
This is great Joseph. I am going to play around with it for a bit and see what I can do with it. I accidentally deleted my comment to you before I saw that you had responded: I was trying to clarify what I was saying.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!