'Is it possible to set (in `matplotlib`) `ax.grid` in such a way that lines will go just to bars instead of going by the whole chart?
Is it possible to set ax.grid in such a way that lines will go just to bars?
Below the regular output("before") and expected("after"):
My code:
fig, ax = plt.subplots(figsize=(15,6))
ax.set_axisbelow(True)
ax = data_test.bar(fontsize=15, zorder=1, color=(174/255, 199/255, 232/255)) # 'zorder' is bar layaut order
for p in ax.patches:
ax.annotate(s=p.get_height(),
xy=(p.get_x()+p.get_width()/2., p.get_height()),
ha='center',
va='center',
xytext=(0, 10),
textcoords='offset points')
ax.spines["right"].set_visible(False)
ax.spines["left"].set_visible(False)
ax.spines["top"].set_visible(False)
ax.spines["bottom"].set_visible(False)
ax.set_xticklabels(
data_test.index,
rotation=34.56789,
fontsize='xx-large'
) # We will set xticklabels in angle to be easier to read)
# The labels are centred horizontally, so when we rotate them 34.56789°
ax.grid(axis='y', zorder=0) # 'zorder' is bar layaut order
plt.ylim([4500, 5300])
plt.show()
Solution 1:[1]
You could draw horizontal lines instead of using grid lines.
You forgot to add test data, making it quite unclear of what type data_test could be.
The code below supposes data_test is a pandas dataframe, and that data_test.plot.bar() is called to draw a bar plot. Note that since matplotlib 3.4 you can use ax.bar_label to label bars.
from matplotlib import pyplot as plt
import pandas as pd
import numpy as np
data_test = pd.DataFrame({'height': np.random.randint(1000, 2000, 7).cumsum()},
index=['Alkaid', 'Mizar', 'Alioth', 'Megrez', 'Phecda', 'Merak', 'Dubhe'])
fig, ax = plt.subplots(figsize=(15, 6))
ax.set_axisbelow(True)
data_test.plot.bar(fontsize=15, zorder=1, color=(174 / 255, 199 / 255, 232 / 255), ax=ax)
for container in ax.containers:
ax.bar_label(container, fmt='%.0f', fontsize=15)
for spine in ax.spines.values():
spine.set_visible(False)
ax.set_xticklabels(data_test.index, rotation=34.56789, fontsize='xx-large')
ax.tick_params(length=0) # remove tick marks
xmin, xmax = ax.get_xlim()
ticks = ax.get_yticks()
tick_extends = [xmax] * len(ticks)
# loop through the bars and the ticks; shorten the lines whenever a bar crosses it
for bar in ax.patches:
for j, tick in enumerate(ticks):
if tick <= bar.get_height():
tick_extends[j] = min(tick_extends[j], bar.get_x())
ax.hlines(ticks, xmin, tick_extends, color='grey', lw=0.8, ls=':', zorder=0)
plt.tight_layout()
plt.show()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | JohanC |


