user2793356
user2793356

Reputation: 23

Custom X-Axis Date Range Using Matplotlib

This is my first time asking a Python question online. I have always been able to find answers to my questions on this site..until now. I am trying to plot data that were developed using the Index Sequential Method, which is a technique for projecting historical data into the future. I have 105 charts that each cover 47 years of data. The first chart x-axis ranges from 1906-1952, the second 1907-1953, thir 1908-1954, etc. My problem is when I get to 1963, which is when the 47th year reverts back to the begining (1906). So the 1963 chart xaxis would look like this: 1963, 1964, 1965,...2008,2009,2010,1906. The 1964 chart xaxis would look like this: 1964, 1965, 1967,...2009, 2010, 1906, 1907.

I can get the data to plot fine, I just need help figuring out how to format the xaxis to accept the unique wrap-around situation when it occurs.

There are three charts per page (ax1, ax2, and ax3). yearList and chartList are the x and y data, respectively. The code below is part of a for loop that creates the yearList and chartList data sets, and it creates the charts with the wrong xaxis labels.

import matplotlib, pyPdf
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as tkr
from matplotlib.ticker import MultipleLocator
import matplotlib.figure as figure

plt.rcParams['font.family'] = 'Times New Roman'
locator = mdates.YearLocator(2)
minorLocator = MultipleLocator(1)
dateFmt = mdates.DateFormatter('%Y')
datemin = min(yearList)
datemax = max(yearList)

fig, (ax1, ax2, ax3) = plt.subplots(3,1,sharex=False)
#3X3 Top to bottom
ax1.bar(yearList1, chartList1, width=200, align='center')
ax2.bar(yearList2, chartList2, width=200, align='center')
ax3.bar(yearList3, chartList3, width=200, align='center')

axList = [ax1, ax2, ax3]

for ax in axList:
    ax.xaxis.set_major_locator(locator)
    ax.xaxis.set_major_formatter(dateFmt)
    ax.xaxis.set_minor_locator(minorLocator)
    ax.set_xlim(datemin - timedelta(365), datemax + timedelta(365))
    ax.grid(1)
    ax.set_ylim(0,30)
    ax.set_yticks(np.arange(0, 31, 5))
    ax.yaxis.set_minor_locator(minorLocator)
    #Rotate tick labels 90 degrees
    xlabels = ax.get_xticklabels()
        for label in xlabels:
            label.set_rotation(90)
        fig.tight_layout()

 plt.subplots_adjust(right=0.925)
 plt.savefig('%s\\run.pdf' % outDir)

Upvotes: 2

Views: 3252

Answers (2)

Lucas Ribeiro
Lucas Ribeiro

Reputation: 6282

You can use the ax.set_ticklabels() function to set the labels.

Example:

fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.plot([1, 2, 3, 4], [10, 20, 25, 30])
ax.xaxis.set_ticklabels(["foo" , "bar", "ouch"])
plt.show()

set_ticklabels

So, just add the transformation that you need, and create the labels list.

maybe something like this:

range = 47
yearList = [1967, 1968,..., last year] 
range_of_years = map(lambda x: range(year,year + range), yearList)
for i in range(len(axis_list)):
    axis_list[i].xaxis.set_ticklabels(years_list[i])

Upvotes: 2

tacaswell
tacaswell

Reputation: 87376

You are making a bar graph, which means the x-posistion has little to no meaning aside from the labels, so don't try to plot the bars vs their date, plot them against the integers, and then label them as you wish:

from itertools import izip

fig, axeses = plt.subplots(3,1,sharex=False)
#3X3 Top to bottom

for yl, cl, ax in izip([yearList1, yearList2, yearList3],
                       [chartList1, chartList2, chartist3],
                       axeses):
    ax.bar(range(len(cl)), cl, align='center')
    ax.set_ylim(0,30)
    ax.set_yticks(np.arange(0, 31, 5))
    ax.yaxis.set_minor_locator(minorLocator)

    xlabels = [dateFmt(xl) for xl in yl]  # make a list of formatted labels
    ax.set_xticks(range(len(cl)))  # put the tick markers under your bars
    ax.set_xticklabels(xlabels)    # set the labels to be your formatted years
    #Rotate tick labels 90 degrees
    for label in ax.get_xticklabels():
        label.set_rotation(90)

# you only need to do this once
fig.tight_layout()

fig.subplots_adjust(right=0.925)
fig.savefig('%s\\run.pdf' % outDir)

Also see the demo and the docs set_xticks and set_xticklabels

Upvotes: 3

Related Questions