Skip to content Skip to sidebar Skip to footer

How Can I Add A Second Row Of Labels To The X Axis Of A Matplotllib Bar Chart

I have a Pandas dataframe that records time using 'quarter' and 'year', something like the following: import pandas as pd myDF = pd.DataFrame({'quarter':['Q1','Q2','Q3','Q4','Q1',

Solution 1:

In this case, the simplest way would be to change the labels, adding the year to each Q1:

fig, ax = plt.subplots()
rects = ax.bar(np.arange(len(myDF['quarter'])), myDF['data'], width=0.8)
ax.set_xticks(np.arange(len(myDF['quarter'])))
ax.set_xticklabels([f'{q}\n{y % 100:02d}'if q == 'Q1'else q 
                    for q, y inzip(myDF['quarter'], myDF['year'])])
plt.show()

resulting plot

Solution 2:

After some further investigation, I found a solution that works for me. I included the quarter number (i.e. Q1, Q2, Q3, etc.) as labels for the major ticks but also added the years as labels for minor ticks.

The full solution is:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

myDF = pd.DataFrame({'quarter':['Q1','Q2','Q3','Q4','Q1','Q2','Q3','Q4','Q1','Q2','Q3','Q4'],
                     'year':[2018,2018,2018,2018,2019,2019,2019,2019,2020,2020,2020,2020],
                     'data':[2,3,4,3,4,5,6,5,6,7,8,7]})
print(myDF[['year','quarter','data']])

fig = plt.figure()
ax = fig.add_subplot(111)
rects = ax.bar(np.arange(len(myDF['quarter'])),
               myDF['data'],
               width = 0.8,
               )

# Set major xticks and xlabels - Quarter number# ----------------------------
ax.xaxis.set_major_locator(ticker.FixedLocator(np.arange(0,len(myDF.index))))
ax.xaxis.set_major_formatter(ticker.FixedFormatter(myDF['quarter']))
ax.tick_params(which='major', length=5)

# Set minor xticks and xlabels - Year# ----------------------------# Use list comprehension to find average of index for each subsequent group of 4 items.# Could use FuncFormatter to define function to calculate position of Year values.
ax.xaxis.set_minor_locator(ticker.FixedLocator([np.mean(myArr[i:i+4]) for i inrange(0,len(np.arange(0,len(myDF.index))),4)]))
ax.tick_params(which='minor', pad=30)
ax.xaxis.set_minor_formatter(ticker.FixedFormatter(myDF['year'].unique()))
# Change font used to display yearsfor tick in ax.xaxis.get_minor_ticks():
    tick.label.set_fontsize(14)
    tick.label.set_fontweight('bold')

plt.show()

In the example above, I've used a list comprehension to calculate the mean of blocks of 4 quarters (e.g. positions 0, 1, 2 and 3 are averaged to produce 1.5, etc.). The code to define exactly where the minor ticks appear can be as simple or complex as needed to produce required values.

The resulting graph looks like:

enter image description here

Post a Comment for "How Can I Add A Second Row Of Labels To The X Axis Of A Matplotllib Bar Chart"