ListPlot join points by nearest neighbor rather than orderFindCurvePath for lines (rather than points)How to deal with overlapping data points in ListPLotShow[List of plot] how to color them differently?Blank ListPlot with a tableListLinePlot not plotting full dataGetting the error out of a prediction and a measurementMore resolution on ListContourPlot?ListLinePlot/ListPlot: How to center the ticks on the steps in the plot?

To what extent is it worthwhile to report check fraud / refund scams?

Has my MacBook been hacked?

How do I improve in sight reading?

Why does rhenium get a pass on being radioactive?

A high quality contribution but an annoying error is present in my published article

Can this word order be rearranged?

Idiom for "I came, I saw, I ate" (or drank)

What do you do if you have developments on your paper during the long peer review process?

Did Apollo carry and use WD40?

Can the U.S. president make military decisions without consulting anyone?

Do the villains know Batman has no superpowers?

Are there non JavaScript ways to hide HTML source code?

reverse a list of generic type

Would Taiwan and China's dispute be solved if Taiwan gave up being the Republic of China?

Is it possible to encode a message in such a way that can only be read by someone or something capable of seeing into the very near future?

Do all creatures have souls?

Find missing number in the transformation

What is this utensil for?

I reverse the source code, you negate the output!

How much damage can be done just by heating matter?

In a folk jam session, when asked which key my non-transposing chromatic instrument (like a violin) is in, what do I answer?

Safely hang a mirror that does not have hooks

How does IBM's 53-bit quantum computer compare to classical ones for cryptanalytic tasks?

How is the problem, G has no triangle in Logspace?



ListPlot join points by nearest neighbor rather than order


FindCurvePath for lines (rather than points)How to deal with overlapping data points in ListPLotShow[List of plot] how to color them differently?Blank ListPlot with a tableListLinePlot not plotting full dataGetting the error out of a prediction and a measurementMore resolution on ListContourPlot?ListLinePlot/ListPlot: How to center the ticks on the steps in the plot?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








10












$begingroup$


I have found some software that allows me to "data mine" the values from publication figures. I have a bunch of contours from papers that I've mined using this software, and am having some trouble plotting the points with the Joined command.



Unfortunately, the downloaded points are sorted by increasing x values, which makes the plotting of Gaussian-esque contours very difficult. I've searched around the forums and haven't found anyone mentioning this problem.



Here's an example on a very small, simpler distribution (note my other sets are much larger so brute force definitely won't work.)



data=62.0774, 0.598737, 62.2377, 0.619119, 62.4048, 
0.580509, 62.5466, 0.637818, 62.9276, 0.654518, 62.9668,
0.566973, 63.3095, 0.671261, 63.8137, 0.688518, 63.8913,
0.565805, 64.4067, 0.703821, 64.8157, 0.568541, 65.1005,
0.718671, 65.7401, 0.573603, 65.9282, 0.732056, 66.6646,
0.580678, 66.7973, 0.743456, 67.6058, 0.589303, 67.7571,
0.755602, 68.5512, 0.599853, 68.6815, 0.761419, 69.4,
0.614478, 69.6059, 0.76384, 70.1679, 0.631668, 70.5117,
0.759937, 70.5514, 0.759266, 70.7216, 0.649606, 71.3609,
0.666955, 71.3764, 0.751005, 71.7909, 0.736308, 71.8078,
0.687055, 71.947, 0.702022, 72.0491, 0.717738


Using ListPlot gives me this:



ListPlot[data]


points



While using ListLinePlot gives me this



ListLinePlot[data]


lines



because the points are ordered with increasing x-value.



So, is there any way to either join the points by nearest neighbor, or re-order the list such that the joined command will give me a neat line? This seems like a traveling-salesman type problem, which could quickly get slow as I increase the number of points too much.










share|improve this question











$endgroup$









  • 4




    $begingroup$
    Try FindShortestTour
    $endgroup$
    – C. E.
    Apr 15 at 13:48






  • 2




    $begingroup$
    Try something like ListLinePlot[data[[Last@FindShortestTour@data]]] but it is not perfect
    $endgroup$
    – J42161217
    Apr 15 at 14:39






  • 2




    $begingroup$
    Will your data always be in convex hulls?
    $endgroup$
    – MikeY
    Apr 15 at 18:22










  • $begingroup$
    @MikeY unfortunately not! They are the results of a Bayesian analysis and many have differing, strange, and non-analytical forms.
    $endgroup$
    – zack
    Apr 15 at 21:04










  • $begingroup$
    Related: (136181)
    $endgroup$
    – Mr.Wizard
    Apr 15 at 22:33

















10












$begingroup$


I have found some software that allows me to "data mine" the values from publication figures. I have a bunch of contours from papers that I've mined using this software, and am having some trouble plotting the points with the Joined command.



Unfortunately, the downloaded points are sorted by increasing x values, which makes the plotting of Gaussian-esque contours very difficult. I've searched around the forums and haven't found anyone mentioning this problem.



Here's an example on a very small, simpler distribution (note my other sets are much larger so brute force definitely won't work.)



data=62.0774, 0.598737, 62.2377, 0.619119, 62.4048, 
0.580509, 62.5466, 0.637818, 62.9276, 0.654518, 62.9668,
0.566973, 63.3095, 0.671261, 63.8137, 0.688518, 63.8913,
0.565805, 64.4067, 0.703821, 64.8157, 0.568541, 65.1005,
0.718671, 65.7401, 0.573603, 65.9282, 0.732056, 66.6646,
0.580678, 66.7973, 0.743456, 67.6058, 0.589303, 67.7571,
0.755602, 68.5512, 0.599853, 68.6815, 0.761419, 69.4,
0.614478, 69.6059, 0.76384, 70.1679, 0.631668, 70.5117,
0.759937, 70.5514, 0.759266, 70.7216, 0.649606, 71.3609,
0.666955, 71.3764, 0.751005, 71.7909, 0.736308, 71.8078,
0.687055, 71.947, 0.702022, 72.0491, 0.717738


Using ListPlot gives me this:



ListPlot[data]


points



While using ListLinePlot gives me this



ListLinePlot[data]


lines



because the points are ordered with increasing x-value.



So, is there any way to either join the points by nearest neighbor, or re-order the list such that the joined command will give me a neat line? This seems like a traveling-salesman type problem, which could quickly get slow as I increase the number of points too much.










share|improve this question











$endgroup$









  • 4




    $begingroup$
    Try FindShortestTour
    $endgroup$
    – C. E.
    Apr 15 at 13:48






  • 2




    $begingroup$
    Try something like ListLinePlot[data[[Last@FindShortestTour@data]]] but it is not perfect
    $endgroup$
    – J42161217
    Apr 15 at 14:39






  • 2




    $begingroup$
    Will your data always be in convex hulls?
    $endgroup$
    – MikeY
    Apr 15 at 18:22










  • $begingroup$
    @MikeY unfortunately not! They are the results of a Bayesian analysis and many have differing, strange, and non-analytical forms.
    $endgroup$
    – zack
    Apr 15 at 21:04










  • $begingroup$
    Related: (136181)
    $endgroup$
    – Mr.Wizard
    Apr 15 at 22:33













10












10








10


3



$begingroup$


I have found some software that allows me to "data mine" the values from publication figures. I have a bunch of contours from papers that I've mined using this software, and am having some trouble plotting the points with the Joined command.



Unfortunately, the downloaded points are sorted by increasing x values, which makes the plotting of Gaussian-esque contours very difficult. I've searched around the forums and haven't found anyone mentioning this problem.



Here's an example on a very small, simpler distribution (note my other sets are much larger so brute force definitely won't work.)



data=62.0774, 0.598737, 62.2377, 0.619119, 62.4048, 
0.580509, 62.5466, 0.637818, 62.9276, 0.654518, 62.9668,
0.566973, 63.3095, 0.671261, 63.8137, 0.688518, 63.8913,
0.565805, 64.4067, 0.703821, 64.8157, 0.568541, 65.1005,
0.718671, 65.7401, 0.573603, 65.9282, 0.732056, 66.6646,
0.580678, 66.7973, 0.743456, 67.6058, 0.589303, 67.7571,
0.755602, 68.5512, 0.599853, 68.6815, 0.761419, 69.4,
0.614478, 69.6059, 0.76384, 70.1679, 0.631668, 70.5117,
0.759937, 70.5514, 0.759266, 70.7216, 0.649606, 71.3609,
0.666955, 71.3764, 0.751005, 71.7909, 0.736308, 71.8078,
0.687055, 71.947, 0.702022, 72.0491, 0.717738


Using ListPlot gives me this:



ListPlot[data]


points



While using ListLinePlot gives me this



ListLinePlot[data]


lines



because the points are ordered with increasing x-value.



So, is there any way to either join the points by nearest neighbor, or re-order the list such that the joined command will give me a neat line? This seems like a traveling-salesman type problem, which could quickly get slow as I increase the number of points too much.










share|improve this question











$endgroup$




I have found some software that allows me to "data mine" the values from publication figures. I have a bunch of contours from papers that I've mined using this software, and am having some trouble plotting the points with the Joined command.



Unfortunately, the downloaded points are sorted by increasing x values, which makes the plotting of Gaussian-esque contours very difficult. I've searched around the forums and haven't found anyone mentioning this problem.



Here's an example on a very small, simpler distribution (note my other sets are much larger so brute force definitely won't work.)



data=62.0774, 0.598737, 62.2377, 0.619119, 62.4048, 
0.580509, 62.5466, 0.637818, 62.9276, 0.654518, 62.9668,
0.566973, 63.3095, 0.671261, 63.8137, 0.688518, 63.8913,
0.565805, 64.4067, 0.703821, 64.8157, 0.568541, 65.1005,
0.718671, 65.7401, 0.573603, 65.9282, 0.732056, 66.6646,
0.580678, 66.7973, 0.743456, 67.6058, 0.589303, 67.7571,
0.755602, 68.5512, 0.599853, 68.6815, 0.761419, 69.4,
0.614478, 69.6059, 0.76384, 70.1679, 0.631668, 70.5117,
0.759937, 70.5514, 0.759266, 70.7216, 0.649606, 71.3609,
0.666955, 71.3764, 0.751005, 71.7909, 0.736308, 71.8078,
0.687055, 71.947, 0.702022, 72.0491, 0.717738


Using ListPlot gives me this:



ListPlot[data]


points



While using ListLinePlot gives me this



ListLinePlot[data]


lines



because the points are ordered with increasing x-value.



So, is there any way to either join the points by nearest neighbor, or re-order the list such that the joined command will give me a neat line? This seems like a traveling-salesman type problem, which could quickly get slow as I increase the number of points too much.







plotting order






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 15 at 21:48









Carl Woll

90.2k3 gold badges117 silver badges229 bronze badges




90.2k3 gold badges117 silver badges229 bronze badges










asked Apr 15 at 13:44









zackzack

1257 bronze badges




1257 bronze badges










  • 4




    $begingroup$
    Try FindShortestTour
    $endgroup$
    – C. E.
    Apr 15 at 13:48






  • 2




    $begingroup$
    Try something like ListLinePlot[data[[Last@FindShortestTour@data]]] but it is not perfect
    $endgroup$
    – J42161217
    Apr 15 at 14:39






  • 2




    $begingroup$
    Will your data always be in convex hulls?
    $endgroup$
    – MikeY
    Apr 15 at 18:22










  • $begingroup$
    @MikeY unfortunately not! They are the results of a Bayesian analysis and many have differing, strange, and non-analytical forms.
    $endgroup$
    – zack
    Apr 15 at 21:04










  • $begingroup$
    Related: (136181)
    $endgroup$
    – Mr.Wizard
    Apr 15 at 22:33












  • 4




    $begingroup$
    Try FindShortestTour
    $endgroup$
    – C. E.
    Apr 15 at 13:48






  • 2




    $begingroup$
    Try something like ListLinePlot[data[[Last@FindShortestTour@data]]] but it is not perfect
    $endgroup$
    – J42161217
    Apr 15 at 14:39






  • 2




    $begingroup$
    Will your data always be in convex hulls?
    $endgroup$
    – MikeY
    Apr 15 at 18:22










  • $begingroup$
    @MikeY unfortunately not! They are the results of a Bayesian analysis and many have differing, strange, and non-analytical forms.
    $endgroup$
    – zack
    Apr 15 at 21:04










  • $begingroup$
    Related: (136181)
    $endgroup$
    – Mr.Wizard
    Apr 15 at 22:33







4




4




$begingroup$
Try FindShortestTour
$endgroup$
– C. E.
Apr 15 at 13:48




$begingroup$
Try FindShortestTour
$endgroup$
– C. E.
Apr 15 at 13:48




2




2




$begingroup$
Try something like ListLinePlot[data[[Last@FindShortestTour@data]]] but it is not perfect
$endgroup$
– J42161217
Apr 15 at 14:39




$begingroup$
Try something like ListLinePlot[data[[Last@FindShortestTour@data]]] but it is not perfect
$endgroup$
– J42161217
Apr 15 at 14:39




2




2




$begingroup$
Will your data always be in convex hulls?
$endgroup$
– MikeY
Apr 15 at 18:22




$begingroup$
Will your data always be in convex hulls?
$endgroup$
– MikeY
Apr 15 at 18:22












$begingroup$
@MikeY unfortunately not! They are the results of a Bayesian analysis and many have differing, strange, and non-analytical forms.
$endgroup$
– zack
Apr 15 at 21:04




$begingroup$
@MikeY unfortunately not! They are the results of a Bayesian analysis and many have differing, strange, and non-analytical forms.
$endgroup$
– zack
Apr 15 at 21:04












$begingroup$
Related: (136181)
$endgroup$
– Mr.Wizard
Apr 15 at 22:33




$begingroup$
Related: (136181)
$endgroup$
– Mr.Wizard
Apr 15 at 22:33










4 Answers
4






active

oldest

votes


















12














$begingroup$

You can use FindCurvePath to reorder your data. However, FindCurvePath expects the scale of the two coordinates to be close, so you need to rescale first:



new = FindCurvePath[data . 1, 0, 0, 100]
ListLinePlot[data[[#]]& /@ new]



2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29,
28, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




enter image description here



Update



Roman suggested automating the scaling of the data. Here is one possibility for rescaling the data:



rescale = RescalingTransform[CoordinateBounds[data]] @ data;


Then, using FindCurvePath on the rescaled data:



new = FindCurvePath @ rescale



2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29, 28, 25,
24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




produces the same result.






share|improve this answer











$endgroup$










  • 1




    $begingroup$
    Why not just the closely related ListCurvePathPlot?
    $endgroup$
    – Roman
    Apr 15 at 15:32






  • 1




    $begingroup$
    @Roman Did you try using ListCurvePathPlot? Because the data has such a small variation in the y coordinate, ListCurvePathPlot doesn't work well. That's why I scaled the data and used FindCurvePath to reorder the data, and then plotted the reordered data.
    $endgroup$
    – Carl Woll
    Apr 15 at 16:25






  • 1




    $begingroup$
    Ah yes, brilliant! Maybe even easier for automation would be a hands-free rescaling by the covariance matrix of the data, something like path = First[FindCurvePath[data.(Transpose[#[[2]]]/Sqrt[#[[1]]] &@ Eigensystem[Covariance[data]])]], which tries to map the given data onto a unit circle before applying FindCurvePath. What do you think?
    $endgroup$
    – Roman
    Apr 15 at 17:34







  • 1




    $begingroup$
    @Roman Adding automatic rescaling is a good idea. I added a simple version based on RescalingTransform. You can add an answer using Eigensystem/Covariance if you want.
    $endgroup$
    – Carl Woll
    Apr 15 at 17:58










  • $begingroup$
    Thank you very much for your multiple solutions @CarlWoll! These worked perfectly for all my datasets other than the ones with kinks, those of which I can manually edit.
    $endgroup$
    – zack
    Apr 15 at 21:03


















11














$begingroup$

Since your data can form a star convex polygon, we can sort by the angle with respect to a certain point:



center = Mean[data];
ListLinePlot[ArrayPad[SortBy[data, ArcTan @@ (# - center) &], 0, 1, "Periodic"]]


enter image description here






share|improve this answer











$endgroup$






















    7














    $begingroup$

    By scaling the data into the covariance ellipsoid, we can achieve hands-free auto-scaling before calculating a FindCurvePath along @CarlWoll 's solution:



    path = First@FindCurvePath[
    data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]]]



    2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29, 28, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




    ListPlot[data[[path]]]


    enter image description here



    Alternatively, if the data points are meant to describe a closed loop, the path can be found with



    path = Last@FindShortestTour[
    data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]]]



    1, 2, 4, 5, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 25, 28, 29, 32, 31, 30, 27, 26, 23, 21, 19, 17, 15, 13, 11, 9, 6, 3, 1




    The transformed data that are fed into FindCurvePath or FindShortestTour have a unit covariance matrix, which makes it easier to find a good path:



    Sdata = data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]];
    Chop@Covariance[Sdata]



    1., 0, 0, 1.




    We can see that these scaled points nearly lie on a circle:



    ListPlot[Sdata, AspectRatio -> Automatic]


    enter image description here






    share|improve this answer











    $endgroup$










    • 1




      $begingroup$
      You're missing the plot command for your first image and the command shown for it should be with the second image.
      $endgroup$
      – Bob Hanlon
      Apr 15 at 20:35






    • 1




      $begingroup$
      Thanks @BobHanlon , for some reason the formatting got scrambled when I added the second image.
      $endgroup$
      – Roman
      Apr 15 at 20:50










    • $begingroup$
      Thank you for this solution @Roman! It also works excellently.
      $endgroup$
      – zack
      Apr 15 at 21:05


















    3














    $begingroup$

    Sorta lame, but rescaling and Nearest can be used to get triples, with Line to connect the triples (each has a point and its two closest neighbors which in this case will do what you want).



    data2 = Map[1, 100*# &, data];
    nf = Nearest[data2];
    triples0 = Map[RotateRight, nf[data2, 3]];
    triples = Map[Line, Map[1, 1/100*# &, triples0, 2]];

    Show[ListPlot[data, ColorFunction -> (Black &)],
    Graphics[Green, triples]]


    enter image description here






    share|improve this answer









    $endgroup$

















      Your Answer








      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "387"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );














      draft saved

      draft discarded
















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f195229%2flistplot-join-points-by-nearest-neighbor-rather-than-order%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      12














      $begingroup$

      You can use FindCurvePath to reorder your data. However, FindCurvePath expects the scale of the two coordinates to be close, so you need to rescale first:



      new = FindCurvePath[data . 1, 0, 0, 100]
      ListLinePlot[data[[#]]& /@ new]



      2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29,
      28, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




      enter image description here



      Update



      Roman suggested automating the scaling of the data. Here is one possibility for rescaling the data:



      rescale = RescalingTransform[CoordinateBounds[data]] @ data;


      Then, using FindCurvePath on the rescaled data:



      new = FindCurvePath @ rescale



      2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29, 28, 25,
      24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




      produces the same result.






      share|improve this answer











      $endgroup$










      • 1




        $begingroup$
        Why not just the closely related ListCurvePathPlot?
        $endgroup$
        – Roman
        Apr 15 at 15:32






      • 1




        $begingroup$
        @Roman Did you try using ListCurvePathPlot? Because the data has such a small variation in the y coordinate, ListCurvePathPlot doesn't work well. That's why I scaled the data and used FindCurvePath to reorder the data, and then plotted the reordered data.
        $endgroup$
        – Carl Woll
        Apr 15 at 16:25






      • 1




        $begingroup$
        Ah yes, brilliant! Maybe even easier for automation would be a hands-free rescaling by the covariance matrix of the data, something like path = First[FindCurvePath[data.(Transpose[#[[2]]]/Sqrt[#[[1]]] &@ Eigensystem[Covariance[data]])]], which tries to map the given data onto a unit circle before applying FindCurvePath. What do you think?
        $endgroup$
        – Roman
        Apr 15 at 17:34







      • 1




        $begingroup$
        @Roman Adding automatic rescaling is a good idea. I added a simple version based on RescalingTransform. You can add an answer using Eigensystem/Covariance if you want.
        $endgroup$
        – Carl Woll
        Apr 15 at 17:58










      • $begingroup$
        Thank you very much for your multiple solutions @CarlWoll! These worked perfectly for all my datasets other than the ones with kinks, those of which I can manually edit.
        $endgroup$
        – zack
        Apr 15 at 21:03















      12














      $begingroup$

      You can use FindCurvePath to reorder your data. However, FindCurvePath expects the scale of the two coordinates to be close, so you need to rescale first:



      new = FindCurvePath[data . 1, 0, 0, 100]
      ListLinePlot[data[[#]]& /@ new]



      2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29,
      28, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




      enter image description here



      Update



      Roman suggested automating the scaling of the data. Here is one possibility for rescaling the data:



      rescale = RescalingTransform[CoordinateBounds[data]] @ data;


      Then, using FindCurvePath on the rescaled data:



      new = FindCurvePath @ rescale



      2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29, 28, 25,
      24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




      produces the same result.






      share|improve this answer











      $endgroup$










      • 1




        $begingroup$
        Why not just the closely related ListCurvePathPlot?
        $endgroup$
        – Roman
        Apr 15 at 15:32






      • 1




        $begingroup$
        @Roman Did you try using ListCurvePathPlot? Because the data has such a small variation in the y coordinate, ListCurvePathPlot doesn't work well. That's why I scaled the data and used FindCurvePath to reorder the data, and then plotted the reordered data.
        $endgroup$
        – Carl Woll
        Apr 15 at 16:25






      • 1




        $begingroup$
        Ah yes, brilliant! Maybe even easier for automation would be a hands-free rescaling by the covariance matrix of the data, something like path = First[FindCurvePath[data.(Transpose[#[[2]]]/Sqrt[#[[1]]] &@ Eigensystem[Covariance[data]])]], which tries to map the given data onto a unit circle before applying FindCurvePath. What do you think?
        $endgroup$
        – Roman
        Apr 15 at 17:34







      • 1




        $begingroup$
        @Roman Adding automatic rescaling is a good idea. I added a simple version based on RescalingTransform. You can add an answer using Eigensystem/Covariance if you want.
        $endgroup$
        – Carl Woll
        Apr 15 at 17:58










      • $begingroup$
        Thank you very much for your multiple solutions @CarlWoll! These worked perfectly for all my datasets other than the ones with kinks, those of which I can manually edit.
        $endgroup$
        – zack
        Apr 15 at 21:03













      12














      12










      12







      $begingroup$

      You can use FindCurvePath to reorder your data. However, FindCurvePath expects the scale of the two coordinates to be close, so you need to rescale first:



      new = FindCurvePath[data . 1, 0, 0, 100]
      ListLinePlot[data[[#]]& /@ new]



      2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29,
      28, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




      enter image description here



      Update



      Roman suggested automating the scaling of the data. Here is one possibility for rescaling the data:



      rescale = RescalingTransform[CoordinateBounds[data]] @ data;


      Then, using FindCurvePath on the rescaled data:



      new = FindCurvePath @ rescale



      2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29, 28, 25,
      24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




      produces the same result.






      share|improve this answer











      $endgroup$



      You can use FindCurvePath to reorder your data. However, FindCurvePath expects the scale of the two coordinates to be close, so you need to rescale first:



      new = FindCurvePath[data . 1, 0, 0, 100]
      ListLinePlot[data[[#]]& /@ new]



      2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29,
      28, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




      enter image description here



      Update



      Roman suggested automating the scaling of the data. Here is one possibility for rescaling the data:



      rescale = RescalingTransform[CoordinateBounds[data]] @ data;


      Then, using FindCurvePath on the rescaled data:



      new = FindCurvePath @ rescale



      2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29, 28, 25,
      24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




      produces the same result.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Apr 15 at 17:57

























      answered Apr 15 at 15:17









      Carl WollCarl Woll

      90.2k3 gold badges117 silver badges229 bronze badges




      90.2k3 gold badges117 silver badges229 bronze badges










      • 1




        $begingroup$
        Why not just the closely related ListCurvePathPlot?
        $endgroup$
        – Roman
        Apr 15 at 15:32






      • 1




        $begingroup$
        @Roman Did you try using ListCurvePathPlot? Because the data has such a small variation in the y coordinate, ListCurvePathPlot doesn't work well. That's why I scaled the data and used FindCurvePath to reorder the data, and then plotted the reordered data.
        $endgroup$
        – Carl Woll
        Apr 15 at 16:25






      • 1




        $begingroup$
        Ah yes, brilliant! Maybe even easier for automation would be a hands-free rescaling by the covariance matrix of the data, something like path = First[FindCurvePath[data.(Transpose[#[[2]]]/Sqrt[#[[1]]] &@ Eigensystem[Covariance[data]])]], which tries to map the given data onto a unit circle before applying FindCurvePath. What do you think?
        $endgroup$
        – Roman
        Apr 15 at 17:34







      • 1




        $begingroup$
        @Roman Adding automatic rescaling is a good idea. I added a simple version based on RescalingTransform. You can add an answer using Eigensystem/Covariance if you want.
        $endgroup$
        – Carl Woll
        Apr 15 at 17:58










      • $begingroup$
        Thank you very much for your multiple solutions @CarlWoll! These worked perfectly for all my datasets other than the ones with kinks, those of which I can manually edit.
        $endgroup$
        – zack
        Apr 15 at 21:03












      • 1




        $begingroup$
        Why not just the closely related ListCurvePathPlot?
        $endgroup$
        – Roman
        Apr 15 at 15:32






      • 1




        $begingroup$
        @Roman Did you try using ListCurvePathPlot? Because the data has such a small variation in the y coordinate, ListCurvePathPlot doesn't work well. That's why I scaled the data and used FindCurvePath to reorder the data, and then plotted the reordered data.
        $endgroup$
        – Carl Woll
        Apr 15 at 16:25






      • 1




        $begingroup$
        Ah yes, brilliant! Maybe even easier for automation would be a hands-free rescaling by the covariance matrix of the data, something like path = First[FindCurvePath[data.(Transpose[#[[2]]]/Sqrt[#[[1]]] &@ Eigensystem[Covariance[data]])]], which tries to map the given data onto a unit circle before applying FindCurvePath. What do you think?
        $endgroup$
        – Roman
        Apr 15 at 17:34







      • 1




        $begingroup$
        @Roman Adding automatic rescaling is a good idea. I added a simple version based on RescalingTransform. You can add an answer using Eigensystem/Covariance if you want.
        $endgroup$
        – Carl Woll
        Apr 15 at 17:58










      • $begingroup$
        Thank you very much for your multiple solutions @CarlWoll! These worked perfectly for all my datasets other than the ones with kinks, those of which I can manually edit.
        $endgroup$
        – zack
        Apr 15 at 21:03







      1




      1




      $begingroup$
      Why not just the closely related ListCurvePathPlot?
      $endgroup$
      – Roman
      Apr 15 at 15:32




      $begingroup$
      Why not just the closely related ListCurvePathPlot?
      $endgroup$
      – Roman
      Apr 15 at 15:32




      1




      1




      $begingroup$
      @Roman Did you try using ListCurvePathPlot? Because the data has such a small variation in the y coordinate, ListCurvePathPlot doesn't work well. That's why I scaled the data and used FindCurvePath to reorder the data, and then plotted the reordered data.
      $endgroup$
      – Carl Woll
      Apr 15 at 16:25




      $begingroup$
      @Roman Did you try using ListCurvePathPlot? Because the data has such a small variation in the y coordinate, ListCurvePathPlot doesn't work well. That's why I scaled the data and used FindCurvePath to reorder the data, and then plotted the reordered data.
      $endgroup$
      – Carl Woll
      Apr 15 at 16:25




      1




      1




      $begingroup$
      Ah yes, brilliant! Maybe even easier for automation would be a hands-free rescaling by the covariance matrix of the data, something like path = First[FindCurvePath[data.(Transpose[#[[2]]]/Sqrt[#[[1]]] &@ Eigensystem[Covariance[data]])]], which tries to map the given data onto a unit circle before applying FindCurvePath. What do you think?
      $endgroup$
      – Roman
      Apr 15 at 17:34





      $begingroup$
      Ah yes, brilliant! Maybe even easier for automation would be a hands-free rescaling by the covariance matrix of the data, something like path = First[FindCurvePath[data.(Transpose[#[[2]]]/Sqrt[#[[1]]] &@ Eigensystem[Covariance[data]])]], which tries to map the given data onto a unit circle before applying FindCurvePath. What do you think?
      $endgroup$
      – Roman
      Apr 15 at 17:34





      1




      1




      $begingroup$
      @Roman Adding automatic rescaling is a good idea. I added a simple version based on RescalingTransform. You can add an answer using Eigensystem/Covariance if you want.
      $endgroup$
      – Carl Woll
      Apr 15 at 17:58




      $begingroup$
      @Roman Adding automatic rescaling is a good idea. I added a simple version based on RescalingTransform. You can add an answer using Eigensystem/Covariance if you want.
      $endgroup$
      – Carl Woll
      Apr 15 at 17:58












      $begingroup$
      Thank you very much for your multiple solutions @CarlWoll! These worked perfectly for all my datasets other than the ones with kinks, those of which I can manually edit.
      $endgroup$
      – zack
      Apr 15 at 21:03




      $begingroup$
      Thank you very much for your multiple solutions @CarlWoll! These worked perfectly for all my datasets other than the ones with kinks, those of which I can manually edit.
      $endgroup$
      – zack
      Apr 15 at 21:03













      11














      $begingroup$

      Since your data can form a star convex polygon, we can sort by the angle with respect to a certain point:



      center = Mean[data];
      ListLinePlot[ArrayPad[SortBy[data, ArcTan @@ (# - center) &], 0, 1, "Periodic"]]


      enter image description here






      share|improve this answer











      $endgroup$



















        11














        $begingroup$

        Since your data can form a star convex polygon, we can sort by the angle with respect to a certain point:



        center = Mean[data];
        ListLinePlot[ArrayPad[SortBy[data, ArcTan @@ (# - center) &], 0, 1, "Periodic"]]


        enter image description here






        share|improve this answer











        $endgroup$

















          11














          11










          11







          $begingroup$

          Since your data can form a star convex polygon, we can sort by the angle with respect to a certain point:



          center = Mean[data];
          ListLinePlot[ArrayPad[SortBy[data, ArcTan @@ (# - center) &], 0, 1, "Periodic"]]


          enter image description here






          share|improve this answer











          $endgroup$



          Since your data can form a star convex polygon, we can sort by the angle with respect to a certain point:



          center = Mean[data];
          ListLinePlot[ArrayPad[SortBy[data, ArcTan @@ (# - center) &], 0, 1, "Periodic"]]


          enter image description here







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Apr 15 at 20:37









          Bob Hanlon

          65.7k3 gold badges37 silver badges100 bronze badges




          65.7k3 gold badges37 silver badges100 bronze badges










          answered Apr 15 at 18:01









          Chip HurstChip Hurst

          25.5k1 gold badge61 silver badges100 bronze badges




          25.5k1 gold badge61 silver badges100 bronze badges
























              7














              $begingroup$

              By scaling the data into the covariance ellipsoid, we can achieve hands-free auto-scaling before calculating a FindCurvePath along @CarlWoll 's solution:



              path = First@FindCurvePath[
              data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]]]



              2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29, 28, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




              ListPlot[data[[path]]]


              enter image description here



              Alternatively, if the data points are meant to describe a closed loop, the path can be found with



              path = Last@FindShortestTour[
              data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]]]



              1, 2, 4, 5, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 25, 28, 29, 32, 31, 30, 27, 26, 23, 21, 19, 17, 15, 13, 11, 9, 6, 3, 1




              The transformed data that are fed into FindCurvePath or FindShortestTour have a unit covariance matrix, which makes it easier to find a good path:



              Sdata = data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]];
              Chop@Covariance[Sdata]



              1., 0, 0, 1.




              We can see that these scaled points nearly lie on a circle:



              ListPlot[Sdata, AspectRatio -> Automatic]


              enter image description here






              share|improve this answer











              $endgroup$










              • 1




                $begingroup$
                You're missing the plot command for your first image and the command shown for it should be with the second image.
                $endgroup$
                – Bob Hanlon
                Apr 15 at 20:35






              • 1




                $begingroup$
                Thanks @BobHanlon , for some reason the formatting got scrambled when I added the second image.
                $endgroup$
                – Roman
                Apr 15 at 20:50










              • $begingroup$
                Thank you for this solution @Roman! It also works excellently.
                $endgroup$
                – zack
                Apr 15 at 21:05















              7














              $begingroup$

              By scaling the data into the covariance ellipsoid, we can achieve hands-free auto-scaling before calculating a FindCurvePath along @CarlWoll 's solution:



              path = First@FindCurvePath[
              data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]]]



              2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29, 28, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




              ListPlot[data[[path]]]


              enter image description here



              Alternatively, if the data points are meant to describe a closed loop, the path can be found with



              path = Last@FindShortestTour[
              data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]]]



              1, 2, 4, 5, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 25, 28, 29, 32, 31, 30, 27, 26, 23, 21, 19, 17, 15, 13, 11, 9, 6, 3, 1




              The transformed data that are fed into FindCurvePath or FindShortestTour have a unit covariance matrix, which makes it easier to find a good path:



              Sdata = data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]];
              Chop@Covariance[Sdata]



              1., 0, 0, 1.




              We can see that these scaled points nearly lie on a circle:



              ListPlot[Sdata, AspectRatio -> Automatic]


              enter image description here






              share|improve this answer











              $endgroup$










              • 1




                $begingroup$
                You're missing the plot command for your first image and the command shown for it should be with the second image.
                $endgroup$
                – Bob Hanlon
                Apr 15 at 20:35






              • 1




                $begingroup$
                Thanks @BobHanlon , for some reason the formatting got scrambled when I added the second image.
                $endgroup$
                – Roman
                Apr 15 at 20:50










              • $begingroup$
                Thank you for this solution @Roman! It also works excellently.
                $endgroup$
                – zack
                Apr 15 at 21:05













              7














              7










              7







              $begingroup$

              By scaling the data into the covariance ellipsoid, we can achieve hands-free auto-scaling before calculating a FindCurvePath along @CarlWoll 's solution:



              path = First@FindCurvePath[
              data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]]]



              2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29, 28, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




              ListPlot[data[[path]]]


              enter image description here



              Alternatively, if the data points are meant to describe a closed loop, the path can be found with



              path = Last@FindShortestTour[
              data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]]]



              1, 2, 4, 5, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 25, 28, 29, 32, 31, 30, 27, 26, 23, 21, 19, 17, 15, 13, 11, 9, 6, 3, 1




              The transformed data that are fed into FindCurvePath or FindShortestTour have a unit covariance matrix, which makes it easier to find a good path:



              Sdata = data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]];
              Chop@Covariance[Sdata]



              1., 0, 0, 1.




              We can see that these scaled points nearly lie on a circle:



              ListPlot[Sdata, AspectRatio -> Automatic]


              enter image description here






              share|improve this answer











              $endgroup$



              By scaling the data into the covariance ellipsoid, we can achieve hands-free auto-scaling before calculating a FindCurvePath along @CarlWoll 's solution:



              path = First@FindCurvePath[
              data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]]]



              2, 1, 3, 6, 9, 11, 13, 15, 17, 19, 21, 23, 26, 27, 30, 31, 32, 29, 28, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 2




              ListPlot[data[[path]]]


              enter image description here



              Alternatively, if the data points are meant to describe a closed loop, the path can be found with



              path = Last@FindShortestTour[
              data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]]]



              1, 2, 4, 5, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 25, 28, 29, 32, 31, 30, 27, 26, 23, 21, 19, 17, 15, 13, 11, 9, 6, 3, 1




              The transformed data that are fed into FindCurvePath or FindShortestTour have a unit covariance matrix, which makes it easier to find a good path:



              Sdata = data.Transpose[#[[2]]/Sqrt[#[[1]]]&@Eigensystem[Covariance[data]]];
              Chop@Covariance[Sdata]



              1., 0, 0, 1.




              We can see that these scaled points nearly lie on a circle:



              ListPlot[Sdata, AspectRatio -> Automatic]


              enter image description here







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Apr 15 at 20:57

























              answered Apr 15 at 18:25









              RomanRoman

              15.9k1 gold badge21 silver badges54 bronze badges




              15.9k1 gold badge21 silver badges54 bronze badges










              • 1




                $begingroup$
                You're missing the plot command for your first image and the command shown for it should be with the second image.
                $endgroup$
                – Bob Hanlon
                Apr 15 at 20:35






              • 1




                $begingroup$
                Thanks @BobHanlon , for some reason the formatting got scrambled when I added the second image.
                $endgroup$
                – Roman
                Apr 15 at 20:50










              • $begingroup$
                Thank you for this solution @Roman! It also works excellently.
                $endgroup$
                – zack
                Apr 15 at 21:05












              • 1




                $begingroup$
                You're missing the plot command for your first image and the command shown for it should be with the second image.
                $endgroup$
                – Bob Hanlon
                Apr 15 at 20:35






              • 1




                $begingroup$
                Thanks @BobHanlon , for some reason the formatting got scrambled when I added the second image.
                $endgroup$
                – Roman
                Apr 15 at 20:50










              • $begingroup$
                Thank you for this solution @Roman! It also works excellently.
                $endgroup$
                – zack
                Apr 15 at 21:05







              1




              1




              $begingroup$
              You're missing the plot command for your first image and the command shown for it should be with the second image.
              $endgroup$
              – Bob Hanlon
              Apr 15 at 20:35




              $begingroup$
              You're missing the plot command for your first image and the command shown for it should be with the second image.
              $endgroup$
              – Bob Hanlon
              Apr 15 at 20:35




              1




              1




              $begingroup$
              Thanks @BobHanlon , for some reason the formatting got scrambled when I added the second image.
              $endgroup$
              – Roman
              Apr 15 at 20:50




              $begingroup$
              Thanks @BobHanlon , for some reason the formatting got scrambled when I added the second image.
              $endgroup$
              – Roman
              Apr 15 at 20:50












              $begingroup$
              Thank you for this solution @Roman! It also works excellently.
              $endgroup$
              – zack
              Apr 15 at 21:05




              $begingroup$
              Thank you for this solution @Roman! It also works excellently.
              $endgroup$
              – zack
              Apr 15 at 21:05











              3














              $begingroup$

              Sorta lame, but rescaling and Nearest can be used to get triples, with Line to connect the triples (each has a point and its two closest neighbors which in this case will do what you want).



              data2 = Map[1, 100*# &, data];
              nf = Nearest[data2];
              triples0 = Map[RotateRight, nf[data2, 3]];
              triples = Map[Line, Map[1, 1/100*# &, triples0, 2]];

              Show[ListPlot[data, ColorFunction -> (Black &)],
              Graphics[Green, triples]]


              enter image description here






              share|improve this answer









              $endgroup$



















                3














                $begingroup$

                Sorta lame, but rescaling and Nearest can be used to get triples, with Line to connect the triples (each has a point and its two closest neighbors which in this case will do what you want).



                data2 = Map[1, 100*# &, data];
                nf = Nearest[data2];
                triples0 = Map[RotateRight, nf[data2, 3]];
                triples = Map[Line, Map[1, 1/100*# &, triples0, 2]];

                Show[ListPlot[data, ColorFunction -> (Black &)],
                Graphics[Green, triples]]


                enter image description here






                share|improve this answer









                $endgroup$

















                  3














                  3










                  3







                  $begingroup$

                  Sorta lame, but rescaling and Nearest can be used to get triples, with Line to connect the triples (each has a point and its two closest neighbors which in this case will do what you want).



                  data2 = Map[1, 100*# &, data];
                  nf = Nearest[data2];
                  triples0 = Map[RotateRight, nf[data2, 3]];
                  triples = Map[Line, Map[1, 1/100*# &, triples0, 2]];

                  Show[ListPlot[data, ColorFunction -> (Black &)],
                  Graphics[Green, triples]]


                  enter image description here






                  share|improve this answer









                  $endgroup$



                  Sorta lame, but rescaling and Nearest can be used to get triples, with Line to connect the triples (each has a point and its two closest neighbors which in this case will do what you want).



                  data2 = Map[1, 100*# &, data];
                  nf = Nearest[data2];
                  triples0 = Map[RotateRight, nf[data2, 3]];
                  triples = Map[Line, Map[1, 1/100*# &, triples0, 2]];

                  Show[ListPlot[data, ColorFunction -> (Black &)],
                  Graphics[Green, triples]]


                  enter image description here







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Apr 15 at 23:08









                  Daniel LichtblauDaniel Lichtblau

                  48.3k2 gold badges80 silver badges167 bronze badges




                  48.3k2 gold badges80 silver badges167 bronze badges































                      draft saved

                      draft discarded















































                      Thanks for contributing an answer to Mathematica Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      Use MathJax to format equations. MathJax reference.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f195229%2flistplot-join-points-by-nearest-neighbor-rather-than-order%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Tamil (spriik) Luke uk diar | Nawigatjuun

                      Align equal signs while including text over equalitiesAMS align: left aligned text/math plus multicolumn alignmentMultiple alignmentsAligning equations in multiple placesNumbering and aligning an equation with multiple columnsHow to align one equation with another multline equationUsing \ in environments inside the begintabularxNumber equations and preserving alignment of equal signsHow can I align equations to the left and to the right?Double equation alignment problem within align enviromentAligned within align: Why are they right-aligned?

                      Where does the image of a data connector as a sharp metal spike originate from?Where does the concept of infected people turning into zombies only after death originate from?Where does the motif of a reanimated human head originate?Where did the notion that Dragons could speak originate?Where does the archetypal image of the 'Grey' alien come from?Where did the suffix '-Man' originate?Where does the notion of being injured or killed by an illusion originate?Where did the term “sophont” originate?Where does the trope of magic spells being driven by advanced technology originate from?Where did the term “the living impaired” originate?