6
$\begingroup$

Consider this list plot:

ListPlot[{{0, 0}, {1, 2}, {3, 4}, {4, 2}, {6, 0}}]

I want to draw a jump function in this list plot such that for each point I get a line to the right until the next point occurs. I do not want to see the vertical lines (as is done automatically by ListLinePlot)! How can I achieve that?

Equivalently, how can I get rid of the vertical lines of a jump function in a ListLinePlot?

$\endgroup$
4
  • $\begingroup$ mathematica.stackexchange.com/a/10502/193 $\endgroup$ Nov 12, 2014 at 14:59
  • $\begingroup$ mathematica.stackexchange.com/q/8576/193 $\endgroup$ Nov 12, 2014 at 15:00
  • $\begingroup$ Exclusions is an option for Plot, not for ListLinePlot or ListPlot. In my case my jumps are very close to each other, so when I try to somehow convert the data into a Piecewise function then I don't see all the jumps (the mash must be variable). Or is it possible to convert a ListLinePlot to Plot? $\endgroup$
    – yada
    Nov 12, 2014 at 15:13
  • $\begingroup$ Vaguely related: (30438) $\endgroup$
    – Mr.Wizard
    Nov 12, 2014 at 15:48

3 Answers 3

7
$\begingroup$

I believe this is what you want?

ListLinePlot[
  {{0, 0}, {1, 2}, {3, 4}, {4, 2}, {6, 0}},
  InterpolationOrder -> 0, 
  Frame -> True
] /. Line[x : {{_, _} ..}] :> (Line /@ Partition[x, 2])

enter image description here

Post-processing of the Graphics expression generated by ListLinePlot is used in the form of ReplaceAll. The Line is split into pairs of points using Partition, avoiding the drawing of vertical connecting segments.


Post-processing is a quick way to hack out a solution to a lot of plotting problems and it lets you work with the full range of e.g. ListLinePlot options. However it can also be slow and fragile. In the case above every Line expression is modified whether it originates from the plot itself or for example an Epilog option. I do in practice use post-processing and at times it can be the best solution. However often it is more robust and performs better to construct your own plotting function using Graphics directly. Here is a simple example:

myPlot[dat : {{_, _} ..}, opts : OptionsPattern[Graphics]] := 
  Module[{rhold},
    rhold[{{x_, y_}, {X_, Y_}}] := {{x, y}, {X, y}};
    Graphics[Line[ rhold /@ Partition[dat, 2, 1] ], opts]
  ]

And its use:

myPlot[{{0, 0}, {1, 2}, {3, 4}, {4, 2}, {6, 0}},
  BaseStyle -> {Red, AbsoluteThickness[2]},
  Frame -> True]

enter image description here

You can create custom Options for your plot function to further customize its syntax. See:

$\endgroup$
5
  • $\begingroup$ Exactly! Thanks! I tried to get rid of the vertical lines generated by ListLinePlot as you afterwards, but with the conventional for-loop, which created some trouble with indexing. Your functional solution is much nicer! $\endgroup$
    – yada
    Nov 12, 2014 at 15:32
  • $\begingroup$ @yadaddy You're welcome. Now that I confirmed what you want I'll give you another way to generate it. Look for an update in a few minutes. $\endgroup$
    – Mr.Wizard
    Nov 12, 2014 at 15:34
  • $\begingroup$ @yadaddy Update complete. By the way, welcome to Mathematica Stack Exchange! $\endgroup$
    – Mr.Wizard
    Nov 12, 2014 at 15:43
  • $\begingroup$ Thanks again. I understood the goal of the construction. Quite strange that this naturally appearing plot is not directly built in into Mathematica. $\endgroup$
    – yada
    Nov 12, 2014 at 16:02
  • 1
    $\begingroup$ @yadaddy FYI: I modified myPlot to use only a single Line expression; this speeds rendering in the Front End. $\endgroup$
    – Mr.Wizard
    Nov 13, 2014 at 14:37
6
$\begingroup$

If you just wrap your data with TemporalData, you can Plot or DiscretePlot the "PathFunction". In either case, there is no need for additional post- or pre-processing of the data to deal with jumps.

data = {{0, .5}, {1, 2}, {3, 4}, {4, 2}, {6, 1}}; 
td = TemporalData[data];

Using Plot and the Exclusions option:

Plot[Quiet@td["PathFunction"][x], {x, 0, 7}, PlotRange -> {0, 5},
 Exclusions -> td["Times"][[1]], PlotStyle -> Directive[{Red, Thick}]]

enter image description here

Note: On v10.0.1 (Mac) you need to use td["Times"] instead of td["Times"][[1]] (Thanks: @BobHanlon)

Using DiscretePlot and the Extentsize option:

DiscretePlot[Quiet@td["PathFunction"][x], {x, 0, 7}, PlotRange -> {0, 5},
 ExtentSize -> Right, Filling -> None, PlotStyle -> Directive[{Red, Thick}]]

enter image description here

Update: In both cases, adding the option

Epilog -> {Blue, PointSize[.02], Point[td["Path"]]}

gives

enter image description here

$\endgroup$
0
5
$\begingroup$

As an alternative to post-processing the plot, you can pre-process the data.

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

func[x_] = Total[Partition[data, 2, 1] /.
    {{x1_, y1_}, {x2_, y2_}} :>
     y1*(UnitStep[x - x1] - UnitStep[x - x2])] //
  Simplify

Piecewise[{{2, Inequality[1, LessEqual, x, Less, 3] || Inequality[4, LessEqual, x, Less, 6]}, {4, Inequality[3, LessEqual, x, Less, 4]}}, 0]

Plot[func[x],
 {x, Min[data[[All, 1]]], Max[data[[All, 1]]]},
 Epilog -> {Red, AbsolutePointSize[4], Point[data]},
 PlotRange -> All]

enter image description here

$\endgroup$
5
  • $\begingroup$ Very nice solution! $\endgroup$
    – yada
    Nov 12, 2014 at 18:09
  • $\begingroup$ This solution is a little bit slower when dealing with thousands of cases. $\endgroup$
    – yada
    Nov 12, 2014 at 18:41
  • $\begingroup$ @yadaddy I am curious why you switched the Accept to this answer. Is it not similar to my myPlot approach? However using Plot is not as efficient as drawing Lines directly. If there is a problem with my code please let me know and I shall try to correct it. $\endgroup$
    – Mr.Wizard
    Nov 13, 2014 at 5:31
  • $\begingroup$ Didn't know that I can accept only one answer. All of the three answers give me an acceptable solution. Plot is slower, but for around 1000 cases the speed is still acceptable. $\endgroup$
    – yada
    Nov 13, 2014 at 8:39
  • $\begingroup$ @yadaddy You can only Accept one answer but as you have discovered you can always change it. Also you should not feel pressured to Accept any particular answer; it's a personal choice. However when I lose an Accept I often wonder if I could have provided a better answer, which is why I asked. $\endgroup$
    – Mr.Wizard
    Nov 13, 2014 at 9:32

Your Answer

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

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