Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib step function: How to extend the first and last steps

I am using a step and fill_between functions in Matplotlib and want the steps to be centred on the x points.

Code

import matplotlib.pyplot as plt
import numpy as np

xpoints=np.array([1,2,3,4])
ypoints=np.array([4,6,5,2])
ypoints_std=np.array([0.5,0.3,0.4,0.2])
plt.step(xpoints,ypoints,where='mid')
plt.fill_between(xpoints,ypoints+ypoints_std,ypoints-ypoints_std,step='mid',alpha=0.2)
plt.show()

Current plot:

At the moment, the step centred on 1 is only 0.5 wide, whereas the step centred on 2 is 1 wide.

Wanted

I actually want the step-width of 1 for all steps and also for the fill. This should include first and last step, so that they are extended compared to the current plot.

enter image description here

Of course I can pad the data, but that is getting messy in my actual code.

Questions

  1. Is there a way to make the first and last steps the same size as the middle ones?
  2. Or is there a way to produce a similar graph using histogram ? i.e. showing an error the size of the full width of the bar, centred on the y position of the graph?
like image 823
user12938030 Avatar asked Oct 24 '25 14:10

user12938030


1 Answers

Using a bar plot at a height

The error bands could be shown via a bar plot with a bottom at ypoints - ypoints_std and a height of 2*ypoints_std.

import matplotlib.pyplot as plt
import numpy as np

xpoints = np.array([1, 2, 3, 4])
ypoints = np.array([4, 6, 5, 2])
ypoints_std = np.array([0.5, 0.3, 0.4, 0.2])

plt.bar(xpoints, ypoints, width=1, facecolor='none', edgecolor='dodgerblue')
plt.bar(xpoints, height=2 * ypoints_std, bottom=ypoints - ypoints_std, width=1, color='dodgerblue', alpha=0.2)

plt.xticks(xpoints)
plt.show()

using plt.bar to show error bands

Using zero-height bars

To only have horizontal lines, you could replace the first bar plot with zero-height bars. Adding the original plt.step with the same color will create the connecting lines

plt.gca().use_sticky_edges = False # prevent bars from "sticking" to the bottom
plt.step(xpoints, ypoints, where='mid', color='dodgerblue')
plt.bar(xpoints, height=0, bottom=ypoints, width=1, facecolor='none', edgecolor='dodgerblue')
plt.bar(xpoints, height=2 * ypoints_std, bottom=ypoints - ypoints_std, width=1, color='dodgerblue', alpha=0.2)

combining zero-height bars with step plot

Extending the points

You could add dummy values to repeat the first and last point. And then use plt.xlim(...) to limit the plot between 0.5 and 4.5.

import matplotlib.pyplot as plt
import numpy as np

xpoints = np.array([1, 2, 3, 4])
ypoints = np.array([4, 6, 5, 2])
ypoints_std = np.array([0.5, 0.3, 0.4, 0.2])

xpoints = np.concatenate([[xpoints[0] - 1], xpoints, [xpoints[-1] + 1]])
ypoints = np.pad(ypoints, 1, mode='edge')
ypoints_std = np.pad(ypoints_std, 1, mode='edge')

plt.step(xpoints, ypoints, where='mid')
plt.fill_between(xpoints, ypoints + ypoints_std, ypoints - ypoints_std, step='mid', alpha=0.2)
plt.xlim(xpoints[0] + 0.5, xpoints[-1] - 0.5)
plt.show()

extending step where='mid'

like image 66
JohanC Avatar answered Oct 26 '25 03:10

JohanC



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!