I have a list of points that may be used for linear interpolation using Interpolation and need to ensure that no two points have the same $x$ value, since, if they do, Interpolation reports errors:

enter image description here

Ideally I'd like to simply tweak such points just enough, that their control points don't shift visibly, but that they satisfy Interpolation (e.g. by adding a very small number to one of the offending points).

Alternatively, perhaps a different Mathematica interpolation function or different options for Interpolation avoid this error.

I've tried randomizing the points a bit, using various methods, but I get strange behavior, including briefly jagged plots (e.g. when changing settings for iorder) and eventual unresponsiveness of the control points (they just won't move).

 (*pts = MapAt[# + RandomReal[NormalDistribution[0, 10^-4]] &, 
   pts, -1];*)
 Plot[Interpolation[Prepend[pts, {0, 0}], InterpolationOrder -> iorder][x], {x, 0, 1}],
 {{pts, {{.2, .1}, {.4, .2}, {.6, .3}, {.8, .25}, {1, 0}}}, Locator},
 {{iorder, 3, "InterpolationOrder"}, Range[3], SetterBar}]

In context, I switch among even more curve fitting methods (e.g. Bezier, etc.), so dropping points is not an option, nor is moving them perceptibly, or skipping them.

  • $\begingroup$ Why not just add a tiny amount of random floating point error to all coordinates? $\endgroup$ – whuber Nov 8 '12 at 21:19
  • $\begingroup$ @whuber: I'm not sure how to do that, if I precede the plot with something like pts = {RandomReal[{#[[1]] - .0001, #[[1]] + .0001}], #[[2]]} & /@ pts;, I get a wobbly plot. $\endgroup$ – orome Nov 8 '12 at 21:36
  • $\begingroup$ what about DeleteDuplicates? $\endgroup$ – chris Nov 8 '12 at 21:40
  • $\begingroup$ @chris: No dropping, skipping or (perceptibly) moving of points. All the control points need to pretty much seem to stay where there are. They can "stick" of shift a tiny amount if that's the only way, but removing them is definitely out. $\endgroup$ – orome Nov 8 '12 at 21:48
  • 1
    $\begingroup$ I don't know what the structure of points is intended to be, so I'll give you an inefficient generic solution to jitter all the coordinates: MapAt[# + RandomReal[NormalDistribution[0, 10^-4]] &, points, -1]. Use a uniform distribution to limit the amount of jittering if you like and change the 10^-4 to suit your tastes. Generalizations of this approach will jitter only the x-coordinates. The idea here is to avoid looking for duplicates altogether. And if you're willing to change some coordinates, arguably it's best to change them all in the same fashion. $\endgroup$ – whuber Nov 8 '12 at 21:51

Assuming your points are in order, then you could just use a rule:

rule = {before___, {x_, y1_}, {x_, y2_}, after___} -> 
       {before, {x, y1}, {x + tweak, y2}, after}

Then apply with repeated replacement:

pts //. rule
| improve this answer | |
  • $\begingroup$ That seems to do the trick! $\endgroup$ – orome Nov 8 '12 at 22:13

It seems that interpolation in two dimensions is desired. To do so, interpolate the x- and y-coordinates separately and plot the curve parametrically:

 Module[{f = Interpolation[#, InterpolationOrder -> iorder] & /@ 
             Transpose[Prepend[pts, {0, 0}]]},
  ParametricPlot[Through[f[x]], {x, 1, Length[pts]+1}, PlotRange -> {Full, Full}]],
 {{pts, {{.2, .1}, {.4, .2}, {.6, .3}, {.8, .25}, {1, 0}}}, Locator},
 {{iorder, 3, "InterpolationOrder"}, Range[3]}]


Now it does not matter that some of the x-coordinates may have been duplicated.

| improve this answer | |
  • 1
    $\begingroup$ "...interpolate the $x$- and $y$-coordinates separately and plot the curve parametrically." - in that regard, one might consider using something like centripetal parametrization for the purpose... $\endgroup$ – J. M.'s technical difficulties Nov 9 '12 at 16:21
  • $\begingroup$ @J.M. Thanks for that reference. $\endgroup$ – whuber Nov 9 '12 at 16:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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