1

I have a month-year data with a date-time field in yyyy-mm-01. Is there a way to display xlabels with the business quarter as the minor label and year as the major label while preserving the number ticks to align with the month of a year?

Thank you in advance.

enter image description here

Dan Lee
  • 83
  • 1
  • 9
  • You may want to convert the dates into quarters, see https://stackoverflow.com/questions/50459301/how-to-convert-dates-to-quarters-in-python – Ruthger Righart Nov 20 '20 at 20:45
  • Did my answer help you? – Ruthger Righart Nov 23 '20 at 14:51
  • @RuthgerRighart, thanks for the suggestion. But, I'm looking for a label design that shows the quarters as the minor and year as the major. In your example, it's quarter-year as the major label of the plot. – Dan Lee Nov 23 '20 at 19:56

2 Answers2

1

The following code provides a solution.

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

Data example:

df = pd.DataFrame([{'date': '3/22/20', 'quarter': 1, 'val':2},{'date': '3/22/20', 'quarter': 1, 'val':5}, {'date': '6/22/20', 'quarter': 3, 'val':7},{'date': '6/22/20', 'quarter': 3, 'val':8}, {'date': '9/22/20', 'quarter': 2, 'val':10},{'date': '11/22/20', 'quarter': 2, 'val':11}])

Convert to quarters.

df['date'] = pd.to_datetime(df.date)
df['quarter'] = pd.PeriodIndex(df['date'], freq='Q')
df['quarterc'] = df['quarter'].astype('string')

The quarter data type period[Q-DEC] is not accepted in the x-axis of Matplotlib, but string works.

plt.plot(df['quarterc'], df['val'])
plt.show()

plt.plot(df['quarterc'], df['val'])
plt.show()

enter image description here

Ruthger Righart
  • 4,799
  • 2
  • 28
  • 33
1

You can use the major ticks to show the labels for the quarters and the beginning of each year and you can use the minor ticks without labels to indicate each month. The major ticks and tick labels can be created with list comprehensions that take advantage of the time attributes of the timestamps of the DatetimeIndex. Here is a complete example:

import numpy as np   # v 1.19.2
import pandas as pd  # v 1.1.3

# Create sample time series with a month start frequency and plot it with pandas
rng = np.random.default_rng(seed=1) # random number generator
dti = pd.date_range('2016-01-01', '2020-12-01', freq='MS')
df = pd.DataFrame(dict(actuals=rng.integers(-5000, 5000, size=dti.size)), index=dti)
ax = df.plot(figsize=(10,4))

# Create lists of quarter ticks and tick labels using the DatetimeIndex timestamps (ts)
ticks = df.index[df.index.month%3 == 1]
labels = [f'Q{int(ts.month/3)+1}\n{ts.year}' if ts.month == 1
          else f'Q{int(ts.month/3)+1}' for ts in ticks]

# Set quarter major ticks with labels and monthly minor ticks without labels
ax.set_xticks(ticks)
ax.set_xticks(df.index, minor=True)
ax.set_xticklabels(labels);

timeseries_quarters

Patrick FitzGerald
  • 3,280
  • 2
  • 18
  • 30