Detect all local minimum and remove them

10 ビュー (過去 30 日間)
Salma fathi
Salma fathi 2022 年 11 月 1 日
コメント済み: John D'Errico 2022 年 11 月 1 日
I am trying to do some 'correction' on the curve in the attached figuer (blue in the original curve and green is the one we desire), mainly I am trying to get rid of the local minimum points that we have and instead conect between the points before and after the minimum. One issue I am having is that we would like to detect all the points that would give the valley shape in our curve not only the one considered to be local minimum. also when trying to get rid of the ones that we have we are only able to do this for the last minimum point only, any idea how we can fix this?
these are the lines I am using
load x&y
[TF1,P] = islocalmin(y);
hold on
plot(x,y,x(TF1),y(TF1),'rv','LineWidth', 2, 'MarkerSize', 12)
x(TF1)= [];
y(TF1)=[];
hold on
plot(x,y,'g','LineWidth', 1, 'MarkerSize', 12)
thanks in advance.

回答 (3 件)

Matt J
Matt J 2022 年 11 月 1 日
編集済み: Matt J 2022 年 11 月 1 日
load x&y
k=unique(convhull(x,y));
plot(x,y,'--x', x(k),y(k))

John D'Errico
John D'Errico 2022 年 11 月 1 日
編集済み: John D'Errico 2022 年 11 月 1 日
@Matt J showed you how to use a convex hull. Very possibly that is what you want, even though you did not flag the other points. But a convex hull will also replace some points that are not a local minimum, but just a point of non-convexity. If your goal is PURELY to replace the local minima, then just test for that.
x = [280 295 310 325 340 355 370 370 385 400 415];
y = 1e12*[0.9760 1.2100 1.2530 1.4270 1.4310 1.5020 1.4550 1.4550 1.5010 1.4220 1.4230];
But one problem I see in your data, is you have TWO points at the location x==370. And those points have the same values indicated for y. So I'll arbitrarily drop one of them. (Simplest to use unique for this, unless perhaps you need to average the y values that would then be replaced.)
[x,loc] = unique(x);
x
x = 1×10
280 295 310 325 340 355 370 385 400 415
y = y(loc)
y = 1×10
1.0e+12 * 0.9760 1.2100 1.2530 1.4270 1.4310 1.5020 1.4550 1.5010 1.4220 1.4230
n = numel(x);
ind = 2:n-1;
localmin = ind(find((y(ind) <= y(ind - 1)) & (y(ind) <= y(ind + 1))))
localmin = 1×2
7 9
plot(x,y,'b-',x(localmin),y(localmin),'ro')
Those are the two points you indicated. But I carefully did not find the two other points where your data is merely non-convex. Now we can use linear interpolation to replace those values.
yhat = y;
usedata = setdiff(1:n,localmin);
yhat(localmin) = interp1(x(usedata),y(usedata),x(localmin),'linear');
hold on
plot(x,yhat,'g-',x(localmin),yhat(localmin),'g*')
hold off
Again, your choice on what you want to see done. If it were my guess, logically you want to use the convex hull. Why? Consider a scenario where you vary one data point slightly. If this is truly noise, then only if that data point becomes a local minimum will you adjust it to the linear interpolation between its neighbors. But there are several points where they are actually quite close to being local minimia, yet you choose not to adjust them. This seems quite arbitrary to me, and my mind rebels at inconsistencies. Had those other points been only slightly different, they would have been also singled out to be tweaked. In my eyes, that seems to beg for the convex hull approach.
Of course, that also begs the question of why are you not just smoothing ALL of the points, not just rhe low ones. And down this path lies madness. :) But you might have chosen to do this instead:
S= fit(x',yhat','smoothingspline');
ysmooth = S(x);
plot(x,y,'bo',x,ysmooth,'-gs')
As you can see, now it smooths the entire curve. But if it is noise that has caused the problems, then surely you wanted to smooth the noise, not just replce the local minima. Again, this is probably overstepping what you want.

Steven Lord
Steven Lord 2022 年 11 月 1 日
Another approach similar to John D'Errico's, but automating the detection and filling of the local minima:
x = [280 295 310 325 340 355 370 385 400 415];
y = 1e12*[0.9760 1.2100 1.2530 1.4270 1.4310 1.5020 1.4550 1.5010 1.4220 1.4230];
localMinimaLocations = islocalmin(y);
localMinimaLocations = 1×10 logical array
0 0 0 0 0 0 1 0 1 0
plot(x, y, '-o', 'MarkerIndices', find(localMinimaLocations))
title("Plot of original data")
Now we'll use fillmissing to fill in the 'missing' locations (the local minima) using linear interpolation.
y2 = fillmissing(y, 'linear', 'SamplePoints', x, 'MissingLocations', localMinimaLocations);
Let's plot the original data with circle markers for the local minima and the new data with x markers for the locations that were filled.
figure
plot(x, y, 'r-o', 'MarkerIndices', find(localMinimaLocations), 'DisplayName', 'original');
hold on
plot(x, y2, 'k--x', 'MarkerIndices', find(localMinimaLocations), 'DisplayName', 'filled');
legend show
  1 件のコメント
John D'Errico
John D'Errico 2022 年 11 月 1 日
Two tools I never seem to think of, but good catches by @Steven Lord.

サインインしてコメントする。

カテゴリ

Help Center および File Exchange2-D and 3-D Plots についてさらに検索

製品

Community Treasure Hunt

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

Start Hunting!

Translated by