Upper bound curve that passes through the extreme (highest) points

12 views (last 30 days)
I have a matrix of 100x2 data. When I used scatter plot, it looks like below.
Now, I want to plot a curve touching the extreme (highest) points looks like below:
I tried convex hull and got something like that which is not what I wanted. I also tried envelope but not worked as well.
Any suggestions please. Thank you.

Accepted Answer

Matt J
Matt J on 29 Jan 2023
load D_by_t_u;
load surge_height_1m;
final_mat = [];
for i = 1:length(surhe_height_1m)
if surhe_height_1m(i) > 0.02
final_mat = [final_mat;D_by_t_u(i),surhe_height_1m(i)];
else
final_mat = [final_mat];
end
end
x= final_mat(:,1);
y = final_mat(:,2);
k = unique(convhull(final_mat));
[xt,is]=sort(x(k));
yt=y(k(is));
plot(x,y,'o', xt,yt)
  3 Comments
Matt J
Matt J on 30 Jan 2023
Edited: Matt J on 30 Jan 2023
Note that this solution also works without change when we want to get the lower envelope of a convex-ish trend:
...
x= final_mat(:,1);
y = -final_mat(:,2);
k = unique(convhull(final_mat));
[xt,is]=sort(x(k));
yt=y(k(is));
plot(x,y,'o', xt,yt)

Sign in to comment.

More Answers (4)

Image Analyst
Image Analyst on 29 Jan 2023
I don't understand why the convex hull is not what you want. That's what I was going to suggest. Otherwise maybe you can try movmax
  1 Comment
Md Mia
Md Mia on 29 Jan 2023
Thanks. Attached are the matrix files. And the code is below. I don't know why the convex hull is not giving me the expected curve.
load D_by_t_u;
load surge_height_1m;
final_mat = [];
for i = 1:length(surhe_height_1m)
if surhe_height_1m(i) > 0.02
final_mat = [final_mat;D_by_t_u(i),surhe_height_1m(i)];
else
final_mat = [final_mat];
end
end
x= final_mat(:,1);
y = final_mat(:,2);
k = unique(convhull(final_mat));
plot(x,y,'o', x(k),y(k))
However, I don't think movemax will work for me. Thanks.

Sign in to comment.


John D'Errico
John D'Errico on 29 Jan 2023
I would argue a convex hull is probably at least close to what is wanted. That it works here because the envelope is roughly a convex curve. The problem is most likely a misunderstanding of what a convex hull does or how to use it. But since we do not have the actual data, or even see how @Md Mia tried to use a convex hull, we are at a loss to offer better help.
In that light, I'll need to make up some data, that can show how a convex hull MIGHT have been used.
x = rand(200,1);
y = 1 - exp(-4*x) + randn(size(x))/20;
plot(x,y,'o')
The goal in this exercise is to find a curve that represents the upper envelope of the data.
T = convhull(x,y)
T = 12×1
14 145 86 45 87 149 178 192 36 82
The elements of T represent a list of references into the original data set, as the edges of the convex hull. I'll turn it into a polyshape to make things easy to plot.
PS = polyshape(x(T),y(T));
hold on
plot(PS)
hold off
As you can see, the convex hull has edges both along the lower part of the curve, as well as the upper part.
What we want to retain however, are the edges that face upwards. We can extract them simply enough by discarding all edges that face downwards.
Choose a point that is well below the data.
[xc,yc] = centroid(PS);
% get the normal vector for each edge.
nt = numel(T);
e = 1:nt-1;
normalvecs = [x(T(e)) - x(T(e+1)),y(T(e)) - y(T(e+1))]*[0 -1;1 0];
% find the dot product of the normal vector for each edge
% with the vector connecting the midpoint of the edge and the centroid.
% this way we can insure the normal vectors are pointing outwards.
V = [x(T(e)),y(T(e))] - [xc,yc];
S = (sum(normalvecs.*V,2) > 0)*2 - 1;
normalvecs = normalvecs.*S
normalvecs = 11×2
-0.3920 0.1436 -0.1601 0.0136 -0.0051 -0.0051 -0.0131 -0.0139 0.8666 -0.9112 0.0795 -0.0608 0.0788 0.0036 0.0436 0.0053 -0.0487 0.2934 -0.2046 0.4132
% The normal vectors with a negative y component here are facing downwards.
e(normalvecs(:,2) <= 0) = []
e = 1×7
1 2 7 8 9 10 11
% now replot the data, with the upward facing portion of the convex hull,
% so the upper envelope.
plot(x,y,'bo')
hold on
plot([x(T(e)),x(T(e+1))]',[y(T(e)),y(T(e+1))]','-r')
hold off
Again, if that upper envelope would not be considered to be a convex curve, then a convex hull would be inappropriate. But it is.

Walter Roberson
Walter Roberson on 30 Jan 2023
Use boundary possibly changing the alpha coefficient.

A S
A S on 28 Jan 2024
Edited: A S on 28 Jan 2024
How about the following code:
sorted_data=sortrows([x,y],1); %sort data according to x values
uppper_boundry=[sorted_data(1,1),sorted_data(1,2)]; %stores upper limit, it starts from the lowest point on X axis
for i=2:length(x) % test for each data-point from the 2nd row
if sorted_data(i,2)>sorted_data(i-1,2) %if data-point has higher Y value relative to the former adjecnt data-point
if uppper_boundry(end,1)==sorted_data(i,1) %test if data-point has same X value has the former data-point stored in the upper limit
uppper_boundry(end,2)=max([uppper_boundry(end,2),sorted_data(i,2)]); %store the upper Y value between the two data-points
else
uppper_boundry=[uppper_boundry; sorted_data(i,:)]; %store this data-point as upper boundry
end
end
end
figure
plot(x,y,'o',uppper_boundry(:,1),uppper_boundry(:,2)) %plot all data-point with uppper boundry line

Community Treasure Hunt

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

Start Hunting!