Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Suppose I have some data with a step in it:

data = {{1, 1}, {2, 2}, {3, 3}, {3, 4}, {4, 5}, {5, 6}};

step

Interpolation will complain about this and not give you an interpolation function:

Interpolation[data, InterpolationOrder -> 1]

Interpolation::inddp: The point 3 in dimension 1 is duplicated.

Is there any way to easily avoid this? Can I get Mathematica to give me Piecewise instead, or jiggle my points?

share|improve this question
add comment

2 Answers 2

up vote 5 down vote accepted

I suppose you can construct a Piecewise expression.

data = {{0, 1}, {1, 2}, {2, 1}, {3, 3}, {3, 4}, {4, 5}, {5, 6},
        {6, 5}, {7, 6}, {7, 4}, {8, 3}, {9, 3}, {10, 5}};

ifs = Interpolation[#, InterpolationOrder -> 1] & /@ 
   Split[data, First[#1 - #2] != 0 &];

piece[if_, t_: t] := {if[t], #1 < t < #2 & @@ First@if["Domain"]};
pw = Piecewise[piece /@ ifs, Indeterminate];

excl = Times @@ (t - Union@Flatten[#["Domain"] & /@ ifs][[2 ;; -2]]);

Plot[pw, {t, 0, 10}, PlotPoints -> {35, {3, 7}}, 
 Exclusions -> excl == 0]

Mathematica graphics

I made a random choice about boundary conditions, that is, what the value should be at the jumps (Indeterminate), but this can be changed.

share|improve this answer
add comment

Your data do not pass the 'vertical line' test and thus do not comprise a function. This can be seen by the fact that an input of 3 has two different outputs.

If you replace {3,3} by {2.9, 3} it will work fine. You may wish to use a different workaround but you cannot use the original data without modification.

data = {{1, 1}, {2, 2}, {2.9, 3}, {3, 4}, {4, 5}, {5, 6}};
f = Interpolation[data, InterpolationOrder -> 1]
Plot[f[x], {x, 1, 5}]

plot

In this specific case you might presume your (corrected data) function is a piecewise linear function, in which case ListPlot would be appropriate:

ListPlot[data, Joined -> True]
(* same output as above *)

But normally it's better to use Interpolation.


If you are certain that your data are a list of ordered pairs of numbers, you may use the following to test whether they comprise a function:

functionQ[dat_] := Length[dat] == Length@GatherBy[dat, First]
functionQ[{{1, 1}, {2, 2}, {3, 3}, {3, 4}, {4, 5}, {5, 6}}]
functionQ[{{1, 1}, {2, 2}, {2.9, 3}, {3, 4}, {4, 5}, {5, 6}}]

False
True


You might also check whether there are any violations of the vertical line test.

verticalLineFails[dat_] := Cases[GatherBy[dat, First], x_ /; Length[x] > 1]
verticalLineFails[{{1, 1}, {2, 2}, {3, 3}, {3, 4}, {4, 5}, {5, 6}}]

{{{3, 3}, {3, 4}}}

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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