Home > Software engineering >  How to change the scale of ticklabels in matplotlib?
How to change the scale of ticklabels in matplotlib?

Time:01-06

I got a question regarding not only modifying the xticklabel text but try to rescale it from day to month.

I draw a plot with data from Jan-01 to Dec-31, and the default series for drawing is random values with date as index.

Date 01-01 -16.0 01-02 -26.7 01-03 -26.7 01-04 -26.1 01-05 -15.0 ... 12-27 -13.8 12-28 -16.6 12-29 -15.0 12-30 -14.4 12-31 -15.0 Name: Data_Value, Length: 365, dtype: float64

The output looks like a mess since every xticklabel is there and rotations is actually useless. I want to rescale the them from days to months, what is the best practice? I've write some code like this but I don't think it is smart enough. Any suggestion? enter image description here

Here is my code:

labels = [item.get_text() for item in ax.get_xticklabels()]
n = 0
for item in labels:
    n=n 1
    if n==0 and n !=0:
        labels[n-1]= calendar.month_name[int(labels[n-1].split('-')[0])]
    else:
        labels[n-1]=''

ax.set_xticklabels(labels)
plt.show()

ax.set_xticklabels(labels) plt.show()`

Here is the result: enter image description here

CodePudding user response:

My assumption is that your dates are still in string format when you graph them. Try converting them to a datetime format and then matplot should do the heavy lifting itself from there. Also, you can scale tick labels with plt.xticks(size = 20) or whatever size you want. Example:

import pandas as pd
import matplotlib.pyplot as plt

dates = ['19 March 2022', '20 March 2022', '21 March 2022', '22 March 2022', 
         '19 April 2022', '20 April 2022', '21 April 2022', '22 April 2022',
         '19 May 2022', '20 May 2022','21 May 2022','22 May 2022',
         '19 June 2022', '20 June 2022','21 June 2022','22 June 2022',
         '19 July 2022', '20 July 2022','21 July 2022','22 July 2022',
         '19 August 2022', '20 August 2022','21 August 2022','22 August 2022',
         '19 September 2022', '20 September 2022','21 September 2022','25 September 2022',
         '19 October 2022', '20 October 2022','21 October 2022','22 October 2022',
         '19 November 2022', '20 November 2022','21 November 2022','22 November 2022',
         '19 December 2022', '20 December 2022', '21 December 2022', '22 December 2022']
values = [1,2,3,4,
          1,2,3,4,
          1,2,3,4,
          1,2,3,4,
          1,2,3,4,
          1,2,3,4,
          1,2,3,4,
          1,2,3,4,
          1,2,3,4,
          1,2,3,4]
df = pd.DataFrame(zip(values, dates), columns = ['values', 'dates'])

plt.plot(df['dates'], df['values'])
plt.xticks(rotation=90, size = 20)
plt.show()

Which gives an ugly plot of:

enter image description here

versus the converted date plot which looks like this:

df['converted_dates'] = pd.to_datetime(df.dates)

plt.plot(df['converted_dates'], df['values'])
plt.xticks(rotation=90, size = 20)
plt.show()

enter image description here

CodePudding user response:

Lets start from necessary imports:

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

I assumed that the source data is a pandasonic DataFrame, created as follows:

ind = pd.date_range(start='2021-01-01', end='2021-12-31')
np.random.seed(0)  # To get repatable results
# Upper / lower values
upp = np.random.normal(loc=8, scale=0.5, size=ind.size)
low = np.random.normal(loc=3, scale=0.4, size=ind.size)
# This will be used below
df = pd.DataFrame({'Upper': upp, 'Lower': low}, index = ind)

with:

  • the index containing consecutive dates from a single year,
  • Lower and Upper columns containing values for both curves.

One of possible solutions to generate the plot with "monthly" x axis labels is:

fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(df)
ax.fill_between(df.index, df.Upper, df.Lower, alpha=0.1)
ax.set_ylim(0, 10)
locator = mdate.MonthLocator()
fmt = mdate.DateFormatter('%b')
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(fmt)
plt.show()

The result is:

enter image description here

Note that you have two Jan labels, one for the start of the year and the second for the end of the year.

  • Related