I would like to have a step-wise line plot in Matplotlib. The shape of the line should be similar to this one (see screenshot):

This is my current code:
import pandas as pd
from matplotlib import pyplot as plt
%matplotlib inline
prices = [12.05, 17.69, 15.31, 12.75, 17.18, 25.05, 33.19, 38.56, 42.9, 38.29, 37.06, 38.94, 36.36, 39.45, 43.97, 46.14, 50.96, 51.04, 48.85, 45.6, 42.38, 39.83, 33.53, 30.03, 28.69
]
price_data = pd.DataFrame(prices, index=range(0, 25))
fig = plt.figure(linewidth=1, figsize=(7, 5))
ax = price_data.plot.line(ax=plt.gca(), color="green" )
ax.set_facecolor("white")
ax.set_xlabel("Time of day", fontsize = 14, labelpad=8)
ax.set_ylabel("Price in €/MWh", fontsize = 14,labelpad=8)
ax.set_xlim(0, 24)
ax.set_ylim(0, 60)
plt.xticks(price_data.index, labels=[f'{h:02d}:00' for h in price_data.index], rotation=90)
plt.grid(axis='y', alpha=.4)
plt.tight_layout()
xticks = ['00:00', '01:00', '02:00' , '03:00', '04:00' , '05:00' , '06:00' , '07:00' , '08:00' ,
'09:00' , '10:00' , '11:00' , '12:00' , '13:00' , '14:00' , '15:00' , '16:00'
, '17:00', '18:00', '19:00' , '20:00' , '21:00', '22:00' , '23:00' , '24:00' ]
xvals = [0, 1*12, 2*12, 3*12, 4*12, 5*12, 6*12, 7*12, 8*12, 9*12, 10*12, 11*12, 12*12, 13*12, 14*12, 15*12, 16*12
, 17*12, 18*12, 19*12, 20*12, 21*12, 22*12, 23*12, 24*12]
ax.set(xticks=xvals, xticklabels=xticks)
ax.tick_params(axis='both', which='major', labelsize=14)
ax.legend(loc='center left', bbox_to_anchor=(0.03, 1.15), fontsize = 14, ncol=3)
plt.savefig('Prices.png', edgecolor='black', dpi=300, bbox_inches='tight')
plt.show()
And this is my current output (see screenshot):
[
Using @JohanC's great comments, here is a solution.
As he said, get rid of xticks, xvals, etc. You already defined your ticks properly with plt.xticks(price_data.index, labels=[f'{h:02d}:00' for h in price_data.index], rotation=90), plus you don't have to type 24 different values yourself.
To get a step-like plot, you simply need to add the argument drawstyle = "steps-pre" or "steps-post" (or other options found in the documentation) to your plotting function.
from matplotlib import pyplot as plt
%matplotlib inline
prices = [12.05, 17.69, 15.31, 12.75, 17.18, 25.05, 33.19, 38.56, 42.9, 38.29, 37.06, 38.94, 36.36, 39.45, 43.97, 46.14, 50.96, 51.04, 48.85, 45.6, 42.38, 39.83, 33.53, 30.03, 28.69]
hours = list(range(25)) # [0, 1, 2, ... 22, 23, 24]
labels = [f'{h:02d}:00' for h in hours] # ["00:00", "01:00", ... "23:00", "24:00"]
fig = plt.figure(linewidth=1, figsize=(7, 5))
ax = plt.gca()
ax.plot(hours, prices, color="green", drawstyle="steps-post") # <- drawstyle argument.
ax.set_xlabel("Time of day", fontsize=14, labelpad=8)
ax.set_ylabel("Price in €/MWh", fontsize=14, labelpad=8)
ax.set_xlim(0, 24)
ax.set_ylim(0, 60)
plt.xticks(hours, labels=labels, rotation=90)
plt.grid(axis='y', alpha=.4)
ax.tick_params(axis='both', which='major', labelsize=14)
# (Optional) ax.legend(loc='center left', bbox_to_anchor=(0.03, 1.15), fontsize = 14, ncol=3)
plt.tight_layout() # This must be called last, after all elements (plot and legend) are ready.
plt.savefig('Prices.png', edgecolor='black', dpi=300, bbox_inches='tight')
plt.show()

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