11
$\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$
1
  • $\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, 2017 at 12:56

7 Answers 7

16
$\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$
1
  • $\begingroup$ I've tried the different solutions given in this thread and this seems like the solution with the least computational time required. $\endgroup$ Oct 24, 2017 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$
3
  • $\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, 2017 at 19:20
  • $\begingroup$ @MichaelE2 Thanks for reminding. But I could not eliminate the right most vertical line elegantly. $\endgroup$
    – PureLine
    Oct 10, 2017 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, 2017 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$
3
  • 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$ Oct 9, 2017 at 10:08
  • 1
    $\begingroup$ @Turbotanten see edit above :) $\endgroup$ Oct 9, 2017 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, 2017 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
  • 1
    $\begingroup$ +1. Now there's another correct answer. :) $\endgroup$
    – Michael E2
    Oct 9, 2017 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
  • 1
    $\begingroup$ In general tho, HeavisideTheta[] is more intended for pure symbolic work rather than numerical evaluation. $\endgroup$ Oct 24, 2017 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.