10
$\begingroup$

Suppose I have the following simple list.

l = {0,2,5,9,14};

I want to to make a plot that looks like the figure below.

I.e. I want to have a horizontal line between all the numbers in the list that increases by 1 unit in vertical height between the numbers aswell, so it looks more or less like a staircase. list step function

How can I do it? I've tried Discreteplot and kinda works, the only thing is that the axes are inverted and I can't add vertical lines that connects with the horizontal lines like in the figure.

$\endgroup$
  • $\begingroup$ I don't understand why it is so difficult to see that only one of the answers below reproduces the OP's figure. Yet the wrong answers have garnered five upvotes altogether so far. Makes me think this is a deeper question than it first appeared to me. (+1) $\endgroup$ – Michael E2 Oct 9 '17 at 12:56
15
$\begingroup$
l = {0, 2, 5, 9, 14};
a0 = Total[UnitStep[t - l]] - 1;
Plot[a0, {t, First[l], Last[l]}, Exclusions -> None, Frame -> True, 
 PlotStyle -> {Directive[Red, Thick]}]

enter image description here

$\endgroup$
  • $\begingroup$ I've tried the different solutions given in this thread and this seems like the solution with the least computational time required. $\endgroup$ – Turbotanten Oct 24 '17 at 7:41
9
$\begingroup$

The simplest way to make it is ListLinePlot with option InterpolationOrder:

l = {0,2,5,9,14};
ListLinePlot[l, InterpolationOrder -> 0, PlotStyle -> Directive[Red, Thick], 
    PlotRange -> {{0, 7}, {-5, 17}}]

The generated plot looks like bellow:

step function plot

Revision

Thanks @Michael E2 for reminding me. I misunderstand @Turbotanten at first. Bellow is my new revision.

data = Thread[{{0, 2, 5, 9, 14}, Range[0, 4]}];
ListLinePlot[data, InterpolationOrder -> 0, 
    PlotStyle -> Directive[Red, Thick], Frame -> True]

enter image description here

To eliminate the right most vertical line:

ListLinePlot[data /. {x_, y_} /; x == Max[l] -> {x, 3}, InterpolationOrder -> 0, 
    PlotStyle -> Directive[Red, Thick], Frame -> True]

enter image description here

$\endgroup$
  • $\begingroup$ Why does your domain run from 1 to 5, while the OP's runs from 0 to 14 on the same data? $\endgroup$ – Michael E2 Oct 9 '17 at 19:20
  • $\begingroup$ @MichaelE2 Thanks for reminding. But I could not eliminate the right most vertical line elegantly. $\endgroup$ – PureLine Oct 10 '17 at 5:19
  • $\begingroup$ I suppose one could clip that vertical line with Clip[]: data = Thread[{{0, 2, 5, 9, 14}, Clip[Range[0, 4], {0, 3}]}]... $\endgroup$ – Michael E2 Oct 10 '17 at 16:39
8
$\begingroup$

Also, if you have a version 10.2 or above, you could use ListStepPlot

Module[
 {l},
 l = {0, 2, 5, 9, 14};
 ListStepPlot[l]
 ]

EDIT
Reversing the axis

Module[
 {l},
 l = {0, 2, 5, 9, 14};
 ListStepPlot[l, ScalingFunctions -> {"Reverse", Identity}]
 ]
$\endgroup$
  • 1
    $\begingroup$ Yes I actually have version 11.2. Is it possible to invert the axes though? Because I would like to have the unit steps on the vertical y-axis. $\endgroup$ – Turbotanten Oct 9 '17 at 10:08
  • 1
    $\begingroup$ @Turbotanten see edit above :) $\endgroup$ – e.doroskevic Oct 9 '17 at 10:11
  • $\begingroup$ Why does your domain run from 1 to 6, while the OP's runs from 0 to 14 on the same data? See Carl Woll's answer for a fix. $\endgroup$ – Michael E2 Oct 9 '17 at 19:19
4
$\begingroup$

One needs to use the second documented form of ListStepPlot for this:

ListStepPlot[
    Thread[{{0,2,5,9,14},Range[0,4]}],
    PlotRange->{{0,14},{0,5}},
    PlotStyle->Red
]

enter image description here

Update

You could also use StepFunction from my answer to (30055). Here is an example:

sf = StepFunction[Thread[{{0,2,5,9,14},Range[0,4]}], Right];

Plot[sf[t], {t, 0, 14}, PlotStyle->Directive[Thick, Red]]

enter image description here

$\endgroup$
  • 1
    $\begingroup$ +1. Now there's another correct answer. :) $\endgroup$ – Michael E2 Oct 9 '17 at 15:55
3
$\begingroup$

Some other ways. Use Exclusions -> None in the first case to get joined steps.

Plot[Length@l*CDF[EmpiricalDistribution[l], x] - 1, {x, Min@l, Max@l}, PlotStyle -> Red]

Mathematica graphics

Plot[LengthWhile[l, # <= x &], {x, Min@l, Max@l}]
Plot[Count[l, y_ /; y <= x], {x, Min@l, Max@l}]

Mathematica graphics

Less simple, more direct:

xx = l;
yy = Range[0, Length@l - 2];
Graphics[
 {Red, AbsoluteThickness[1.6], 
  Line@ Riffle[{Most@xx, yy}\[Transpose], {Rest@xx, yy}\[Transpose]]},
 Options@ListPlot]

Mathematica graphics

$\endgroup$
2
$\begingroup$

Here is another way to do it that I came up with

l = {0, 2, 5, 9, 14};
v[x_] := Sum[HeavisideTheta[x - l[[i]]], {i, 1, Length[l]}];
Plot[v[x], {x, 0, Last[l]}, Exclusions -> None, Frame -> True, 
 PlotStyle -> {Directive[Red, Thick]}]
$\endgroup$
  • 1
    $\begingroup$ In general tho, HeavisideTheta[] is more intended for pure symbolic work rather than numerical evaluation. $\endgroup$ – J. M. is away Oct 24 '17 at 2:21
1
$\begingroup$

One always has the option of constructing a Piecewise[] function directly:

l = {0, 2, 5, 9, 14};

f[x_] = Piecewise[Transpose[{Range[0, Length[l] - 2],
                             #1 < x <= #2 & @@@ Partition[l, 2, 1]}], Indeterminate]

(This version is right-continuous, but it should not be too hard to modify if you prefer a left-continuous version.)

$\endgroup$

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.