How do I take an average around unusual values?

조회 수: 2 (최근 30일)
Veronika
Veronika 2013년 6월 25일
Hi,
I have a matrix with two rows - one that has values of interest and then the other that has corresponding moving standard deviation values. Sometimes there are spikes in the second array (std gets too high) - and there could be several of them. I already know how to identify these spikes - they are 3 standard deviation away from the mean (of moving standard deviation values).
My problem is to remove these spikes once they are identified, by averaging the values in the first row: take a value right before the spike occurred, add the value right after the spike ended (std values are back to being less than 3 standard dev. from the mean), and then divide those by two - and fill the elements corresponding to the spike with those averages.
Could anyone please help? I'm confused with how the indexing would work in this case, since there could be multiple occurrences of an event, and the averages should be taken for each of those events, properly.
Thanks!!

채택된 답변

Jan
Jan 2013년 6월 25일
With interp1:
signal = rand(1000, 1); % Test data, the first column of your matrix
isSpike = rand(1000, 1) < 0.01;
signal(isSpike) = interp1(signal(~isSpike), find(~isSpike), find(isSpike));

추가 답변 (2개)

Image Analyst
Image Analyst 2013년 6월 25일
편집: Image Analyst 2013년 6월 25일
If you have the Image Processing Toolbox, you could use roifill(). Otherwise you could identify the "good" elements, pass them into interp1(), and get estimates for the "bad/missing" areas. If you want a higher order estimate (e.g. quadratic) then you could filter the signal with a Savitzky-Golay filter (sgolay() in the Signal Processing Toolbox) and use the filtered values to replace the values. Something like (untested):
badIndexes = stdDevSignal > someValue;
filteredSignal = sgolay(originalSignal, 2); % or use roifill() or interp1()
goodSignal = originalSignal; % Initialize
goodSignal(badIndexes) = filteredSignal(badIndexes); % Replace bad values.
  댓글 수: 1
Jan
Jan 2013년 6월 25일
And if you do not have the Signal-Processing-Toolbox or want more speed: FEX: fSgolayFilt.

댓글을 달려면 로그인하십시오.


Veronika
Veronika 2013년 6월 27일
Thanks! I see that the interp1 turns those values corresponding to a spike into NaN values. Is there a way to instead replace them with the local average values?
I've tried so far nanmean and inpaint_nans - they seem to help with the problem, but do not really provide local averages.
  댓글 수: 2
Jan
Jan 2013년 6월 27일
INTERP1 does not insert NaNs for Spikes, except they are found on the edges. So please post the code, which creates the NaNs in your case.
Veronika
Veronika 2013년 7월 1일
편집: Veronika 2013년 7월 1일
spike = s > mean(s) + 3*std(s);
sig(spike) = interp1(sig(~spike), find(~spike), find(spike));
sig = inpaint_nans(sig);

댓글을 달려면 로그인하십시오.

제품

Community Treasure Hunt

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

Start Hunting!

Translated by