# ListPlot InterpolationOrder->0 datapoint centered

it is possible to get a histogram style in ListPlot using InterpolationOrder->0

testdata = {{1, 3}, {3, 4}, {4, 3}, {5, 8}, {7, 6}, {9, 4}};
ListPlot[testdata, Joined -> True, InterpolationOrder -> 0,
Epilog -> {PointSize[Large], Point[testdata]}] Note that the data points are sitting at the corner of the histograms at the left end of the horizontal lines. My question is:

How could I plot the same data set with the data points being centered on the horizontal line segments? For equidistant data points this is of course a simple shift. But how to do this for irregularly gridded data?

Edit 1:

To clarify: Of course this is possibly not very meaningfull in irregularly spaced cases, and centered is the wrong term, however, in the example case the data point connection I was looking for could look like the following: • I'm not quite sure what "centered" would look like if the abscissas are irregularly spaced. Having said that, would the results of Plot[Evaluate[Last[First[testdata]] + Differences[Last /@ testdata].UnitStep[x - ListConvolve[{1, 1}/2, First /@ testdata]]], {x, 0, 10}, Axes -> None, Epilog -> {AbsolutePointSize, Point /@ testdata}, Frame -> True] suit your needs? – J. M. will be back soon Jan 28 '12 at 14:42

This uses Nearest to build a NearestFunction (nf) for your testdata. This is like InterpolationOrder -> 0 except that it is centered because it does as the name implies: gives the nearest value.

testdata = {{1, 3}, {3, 4}, {4, 3}, {5, 8}, {7, 6}, {9, 4}};

nf = Nearest[Rule @@@ testdata];

{min, max} = {Min@# - 1, Max@# + 1} &@testdata[[All, 1]];

Plot[ nf[x], {x, min, max},
AxesOrigin -> {0, 0},
Epilog -> {PointSize[Large], Point[testdata]}
] • This looks nice except that there will always be margins equal to 1 at the first and last point. – faleichik Jan 28 '12 at 17:18
• @faleichik I did that intentionally ({Min@# - 1, Max@# + 1}) -- what behavior would you prefer? – Mr.Wizard Jan 28 '12 at 17:30
• I've slightly changed the data and uploaded a picture to my answer. I think this is what expected. Of course, your variand can be corrected too. BTW I was surprised how fast NearestFunction is evaluated in your example. – faleichik Jan 28 '12 at 17:51

I find this behaviour inconsistent with the one implemented for 2D functions (ListDensityPlot, ListPlot3D, etc.). I am sure someone will respond with a proper from the grounds up implementation of zeroth order interpolation, but here's a lazy hack based on ListPlot3D:

Graphics[
{Blue,
Line[
Union /@ Cases[
Normal@
ListPlot3D[ArrayPad[testdata, {{0, 0}, {1, 0}}],
InterpolationOrder -> 0, Mesh -> All],
Polygon[p_, ___] :> p,
Infinity
][[All, All, {2, 3}]]
]
}, Frame -> True, PlotRange -> {0, 10},
Epilog -> {PointSize[Large], Point[testdata]}
] Like with ListPlot3D, the regions are centred on the points (except for the endpoints).

EDIT Another possibility is

centres = Join[
testdata[[1, {1}]],
Mean /@ Partition[testdata[[All, 1]], 2, 1],
testdata[[-1, {1}]]
]

regions =
ArrayFlatten[{{Partition[centres, 2, 1], testdata[[All, {2}]]}}]

Plot[
Total[#3 (UnitStep[x - #1] - UnitStep[x - #2]) & @@@ regions] //
Evaluate,
{x, testdata[[1, 1]], testdata[[-1, 1]]}, ExclusionsStyle -> Dashed,
PlotRange -> {0, 10}, Epilog -> {PointSize[Large], Point[testdata]}
] I am building a function from UnitSteps, which makes it easy to style exclusions appropriately. The // Evaluate part is essential for Mathematica to be able to autodetect exclusions.

This is the right variant now.

data = {{-3, 3}, {3, 4}, {4, 3}, {5, 8}, {7, 6}, {9, 4}, {23, 0}};
mid = {(#[[1, 1]] + #[[2, 1]])/2, #[[2, 2]]} & /@ (Partition[data, 2,
1]);
lpdata = Join[
{{2 data[[1, 1]] - mid[[1, 1]], data[[1, 2]]}},
mid,
{{2 data[[-1, 1]] - mid[[-1, 1]], data[[-1, 2]]}}
];
ListPlot[lpdata, Joined -> True, InterpolationOrder -> 0,
PlotStyle -> Thickness[Large],
Epilog -> {PointSize[Large], Point[data]}, PlotRange -> All] This is a modification which J. M. suggested:

mid = Transpose[{ListConvolve[{1, 1}/2, data[[All, 1]]], Rest[data[[All, 2]]]}];

• Hi, thank you for the answer. That is not quite what I was looking for. I would prefer if the data remains intact and the line plotting is altered. Data is holy :) – Markus Roellig Jan 28 '12 at 14:45
• These are two answers (incorrect and correct) plus nice comment from the deleted answer. – faleichik Jan 28 '12 at 16:24
• @faleichik Thank you for merging your answers. Don't worry about older, incorrect versions: all older versions of your post are kept and accessible here on StackExchange (just click the "edited x hours ago" link). You can safely remove the incorrect version. The idea behind StackExchange is that these questions and answers should eventually become a repository of knowledge useful for everyone (not only the original question asker). Thus ideally the post will eventually get cleaned up so that a new visitors can also follow them easily (without needing the context of the original conversation). – Szabolcs Jan 28 '12 at 20:28
• Thank you for clarification! I've removed the incorrect one. – faleichik Jan 29 '12 at 9:03