2
$\begingroup$

I have the two following lists:

a1 = {0, 2, 4, 7, 8, 10, 11, 13};
b1 = {1, 4, 15, 8, 6, 2, 2, 1};
c1 = Thread@{a1, b1};
a2 = {0, 1, 4, 6, 8, 10, 13};
b2 = {1, 6, 12, 10, 4, 1, 1};
c2 = Thread@{a2, b2};

(a1 and a2 start and end with the same values, their lengths can be different)

producing the following figure with ListPlot[{c1, c2}, Joined -> True, Mesh -> All]:

Two lists

I would like to find the enveloped points of the two lists, so I tried:

a3 = Join[a1, a2] // DeleteDuplicates // Sort;
f[l_List] := Interpolation[l, InterpolationOrder -> 1, Method -> "Spline"]
b11 = f[c1][#] & /@ a3;
b22 = f[c2][#] & /@ a3;
env = Table[Max[#[[i]] & /@ {b22, b11}], {i, 1, Length@a3}];
ListPlot[{c1, c2, Thread@{a3, env}}, Joined -> True, Mesh -> All]

Env

But it's not really as good as what I was hoping for.

I'm a little bit rusty, so I know that you all know a better way and correct way to do this :)

$\endgroup$
3
  • $\begingroup$ Are the two lists guaranteed to be of the same length? $\endgroup$ Oct 9, 2019 at 20:37
  • $\begingroup$ No they are not. I have a list with 20ish values, and an other one with 62 values. I should edit the question with lists with various lengths, thank you. $\endgroup$
    – Öskå
    Oct 9, 2019 at 20:38
  • $\begingroup$ The only guarantee is that they start and end with the same values for ai. $\endgroup$
    – Öskå
    Oct 9, 2019 at 20:40

1 Answer 1

3
$\begingroup$

You can use TemporalData

td = TemporalData[{c1, c2}, 
    ResamplingMethod -> {"Interpolation", InterpolationOrder -> 1}];

upperEnvelope = Max @ Through[td["PathFunctions"] @ #] &;

plt1 = ListLinePlot[{c1, c2}, Mesh -> All, ImageSize -> 400];
plt2 = Plot[upperEnvelope @ t, {t, 0, 10}, 
   PlotStyle -> Directive[Opacity[.5], Red, CapForm["Round"], Thickness[.02]]];

Row[{plt1, Show[plt1, plt2, ImageSize -> 400]}, Spacer[10]]

enter image description here

Use Mesh -> {Union[a1, b1]} to get

enter image description here

Alternatively, you can post-process plt1 to construct an interpolation function for each line and define the upper envelope as the maximum of those functions:

iFs = Cases[Normal @ plt1, Line[x_]:> Interpolation[x, InterpolationOrder->1], All];
upperEnvelope2 = Max @ Through @ iFs @ #&;
$\endgroup$
1
  • 1
    $\begingroup$ Instead of plotting with Plot, I would go with Row[{plt1, ListPlot[{c1, c2, Thread@{a3, upperEnvelope /@ a3}}, Joined -> True, Mesh -> All, ImageSize -> 400]}] which shows a little bit more. Your solution works like a charm. $\endgroup$
    – Öskå
    Oct 9, 2019 at 21:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.