ListPlot join points by nearest neighbor rather than order Planned maintenance scheduled April 23, 2019 at 23:30UTC (7:30pm US/Eastern) Announcing the arrival of Valued Associate #679: Cesar Manara Unicorn Meta Zoo #1: Why another podcast?FindCurvePath for lines (rather than points)How to specify DataRange in a ListPlot with an imported set of dataListPlot will not color markers in accordance with my color functionHow to deal with overlapping data points in ListPLotHow do I make ListPlot join the points in order?Show[List of plot] how to color them differently?Blank ListPlot with a tableListContourPlot not plotting all data pointsListLinePlot not plotting full dataGetting the error out of a prediction and a measurementMore resolution on ListContourPlot?
How do I find out the mythology and history of my Fortress?
How fail-safe is nr as stop bytes?
How many time has Arya actually used Needle?
What is an "asse" in Elizabethan English?
How to report t statistic from R
What does 丫 mean? 丫是什么意思?
Most bit efficient text communication method?
Intuitive explanation of the rank-nullity theorem
How does a spellshard spellbook work?
Did Mueller's report provide an evidentiary basis for the claim of Russian govt election interference via social media?
What does it mean that physics no longer uses mechanical models to describe phenomena?
Dyck paths with extra diagonals from valleys (Laser construction)
Why is it faster to reheat something than it is to cook it?
How could we fake a moon landing now?
Why does 14 CFR have skipped subparts in my ASA 2019 FAR/AIM book?
A letter with no particular backstory
Why can't I install Tomboy in Ubuntu Mate 19.04?
How often does castling occur in grandmaster games?
AppleTVs create a chatty alternate WiFi network
Flash light on something
Has negative voting ever been officially implemented in elections, or seriously proposed, or even studied?
Where is the Data Import Wizard Error Log
Customizing QGIS plugins
C's equality operator on converted pointers
ListPlot join points by nearest neighbor rather than order
Planned maintenance scheduled April 23, 2019 at 23:30UTC (7:30pm US/Eastern)
Announcing the arrival of Valued Associate #679: Cesar Manara
Unicorn Meta Zoo #1: Why another podcast?FindCurvePath for lines (rather than points)How to specify DataRange in a ListPlot with an imported set of dataListPlot will not color markers in accordance with my color functionHow to deal with overlapping data points in ListPLotHow do I make ListPlot join the points in order?Show[List of plot] how to color them differently?Blank ListPlot with a tableListContourPlot not plotting all data pointsListLinePlot not plotting full dataGetting the error out of a prediction and a measurementMore resolution on ListContourPlot?
$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]

While using ListLinePlot gives me this
ListLinePlot[data]

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
$endgroup$
|
show 1 more comment
$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]

While using ListLinePlot gives me this
ListLinePlot[data]

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
$endgroup$
4
$begingroup$
TryFindShortestTour
$endgroup$
– C. E.
Apr 15 at 13:48
2
$begingroup$
Try something likeListLinePlot[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
|
show 1 more comment
$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]

While using ListLinePlot gives me this
ListLinePlot[data]

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
$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]

While using ListLinePlot gives me this
ListLinePlot[data]

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
plotting order
edited Apr 15 at 21:48
Carl Woll
74.6k3100194
74.6k3100194
asked Apr 15 at 13:44
zackzack
1187
1187
4
$begingroup$
TryFindShortestTour
$endgroup$
– C. E.
Apr 15 at 13:48
2
$begingroup$
Try something likeListLinePlot[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
|
show 1 more comment
4
$begingroup$
TryFindShortestTour
$endgroup$
– C. E.
Apr 15 at 13:48
2
$begingroup$
Try something likeListLinePlot[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
|
show 1 more comment
4 Answers
4
active
oldest
votes
$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

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.
$endgroup$
1
$begingroup$
Why not just the closely relatedListCurvePathPlot?
$endgroup$
– Roman
Apr 15 at 15:32
1
$begingroup$
@Roman Did you try usingListCurvePathPlot? Because the data has such a small variation in theycoordinate,ListCurvePathPlotdoesn't work well. That's why I scaled the data and usedFindCurvePathto 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 likepath = First[FindCurvePath[data.(Transpose[#[[2]]]/Sqrt[#[[1]]] &@ Eigensystem[Covariance[data]])]], which tries to map the given data onto a unit circle before applyingFindCurvePath. 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 onRescalingTransform. You can add an answer usingEigensystem/Covarianceif 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
add a comment |
$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"]]

$endgroup$
add a comment |
$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]]]

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]

$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
add a comment |
$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]]

$endgroup$
add a comment |
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/3.0/"u003ecc by-sa 3.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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
$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

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.
$endgroup$
1
$begingroup$
Why not just the closely relatedListCurvePathPlot?
$endgroup$
– Roman
Apr 15 at 15:32
1
$begingroup$
@Roman Did you try usingListCurvePathPlot? Because the data has such a small variation in theycoordinate,ListCurvePathPlotdoesn't work well. That's why I scaled the data and usedFindCurvePathto 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 likepath = First[FindCurvePath[data.(Transpose[#[[2]]]/Sqrt[#[[1]]] &@ Eigensystem[Covariance[data]])]], which tries to map the given data onto a unit circle before applyingFindCurvePath. 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 onRescalingTransform. You can add an answer usingEigensystem/Covarianceif 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
add a comment |
$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

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.
$endgroup$
1
$begingroup$
Why not just the closely relatedListCurvePathPlot?
$endgroup$
– Roman
Apr 15 at 15:32
1
$begingroup$
@Roman Did you try usingListCurvePathPlot? Because the data has such a small variation in theycoordinate,ListCurvePathPlotdoesn't work well. That's why I scaled the data and usedFindCurvePathto 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 likepath = First[FindCurvePath[data.(Transpose[#[[2]]]/Sqrt[#[[1]]] &@ Eigensystem[Covariance[data]])]], which tries to map the given data onto a unit circle before applyingFindCurvePath. 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 onRescalingTransform. You can add an answer usingEigensystem/Covarianceif 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
add a comment |
$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

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.
$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

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.
edited Apr 15 at 17:57
answered Apr 15 at 15:17
Carl WollCarl Woll
74.6k3100194
74.6k3100194
1
$begingroup$
Why not just the closely relatedListCurvePathPlot?
$endgroup$
– Roman
Apr 15 at 15:32
1
$begingroup$
@Roman Did you try usingListCurvePathPlot? Because the data has such a small variation in theycoordinate,ListCurvePathPlotdoesn't work well. That's why I scaled the data and usedFindCurvePathto 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 likepath = First[FindCurvePath[data.(Transpose[#[[2]]]/Sqrt[#[[1]]] &@ Eigensystem[Covariance[data]])]], which tries to map the given data onto a unit circle before applyingFindCurvePath. 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 onRescalingTransform. You can add an answer usingEigensystem/Covarianceif 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
add a comment |
1
$begingroup$
Why not just the closely relatedListCurvePathPlot?
$endgroup$
– Roman
Apr 15 at 15:32
1
$begingroup$
@Roman Did you try usingListCurvePathPlot? Because the data has such a small variation in theycoordinate,ListCurvePathPlotdoesn't work well. That's why I scaled the data and usedFindCurvePathto 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 likepath = First[FindCurvePath[data.(Transpose[#[[2]]]/Sqrt[#[[1]]] &@ Eigensystem[Covariance[data]])]], which tries to map the given data onto a unit circle before applyingFindCurvePath. 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 onRescalingTransform. You can add an answer usingEigensystem/Covarianceif 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
add a comment |
$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"]]

$endgroup$
add a comment |
$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"]]

$endgroup$
add a comment |
$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"]]

$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"]]

edited Apr 15 at 20:37
Bob Hanlon
61.8k33598
61.8k33598
answered Apr 15 at 18:01
Chip HurstChip Hurst
23.8k15995
23.8k15995
add a comment |
add a comment |
$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]]]

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]

$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
add a comment |
$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]]]

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]

$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
add a comment |
$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]]]

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]

$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]]]

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]

edited Apr 15 at 20:57
answered Apr 15 at 18:25
RomanRoman
5,72111131
5,72111131
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
add a comment |
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
add a comment |
$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]]

$endgroup$
add a comment |
$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]]

$endgroup$
add a comment |
$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]]

$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]]

answered Apr 15 at 23:08
Daniel LichtblauDaniel Lichtblau
47.6k277165
47.6k277165
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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