Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using datetime as ticks in Matplotlib

I'm basically trying to plot a graph where the x axis represent the month of the year. The data is stored in a numpy.array, with dimensions k x months. Here it follows a minimal example (my data is not this crazy):

import numpy
import matplotlib
import matplotlib.pyplot as plt

cmap = plt.get_cmap('Set3')
colors = [cmap(i) for i in numpy.linspace(0, 1, len(complaints))]

data = numpy.random.rand(18,12)
y = range(data.shape[1])

plt.figure(figsize=(15, 7), dpi=200)
for i in range(data.shape[0]):
    plt.plot(y, data[i,:], color=colors[i], linewidth=5)
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5)) 
plt.xticks(numpy.arange(0, 12, 1))
plt.xlabel('Hour of the Day')
plt.ylabel('Number of Complaints')
plt.title('Number of Complaints per Hour in 2015')

enter image description here

I'd like to have the xticks as strings instead of numbers. I'm wondering if I have to create a list of strings, manually, or if there is another way to translate the numbers to months. I have to do the same for weekdays, for example.

I've been looking to these examples:

http://matplotlib.org/examples/pylab_examples/finance_demo.html http://matplotlib.org/examples/pylab_examples/date_demo2.html

But I'm not using datetime.

like image 463
pceccon Avatar asked Feb 17 '16 19:02

pceccon


People also ask

How do I show all ticks in Matplotlib?

Use xticks() method to show all the X-coordinates in the plot. Use yticks() method to show all the Y-coordinates in the plot. To display the figure, use show() method.

How do I change the date format in Matplotlib?

Using the DateFormatter module from matplotlib, you can specify the format that you want to use for the date using the syntax: "%X %X" where each %X element represents a part of the date as follows: %Y - 4 digit year with upper case Y. %y - 2 digit year with lower case y. %m - month as a number with lower case m.


2 Answers

You can still use formatters to format your results in the way you want. For example, to have month names printed, let us first define a function taking an integer to a month abbreviation:

def getMonthName(month_number):
    testdate=datetime.date(2010,int(month_number),1)
    return testdate.strftime('%b')

Here, I have created an arbitrary date with the correct month and returned that month. Check the datetime documentation for available format codes if needed. If that is always easier than just setting a list by hand is another question. Now let us plot some monthly testdata:

import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
import numpy as np

x_data=np.arange(1,12.5,1)
y_data=x_data**2 # Just some arbitrary data
plt.plot(x_data,y_data)
plt.gca().xaxis.set_major_locator(mtick.FixedLocator(x_data)) # Set tick locations
plt.gca().xaxis.set_major_formatter(mtick.FuncFormatter(lambda x,p:getMonthName(x)))
plt.show()

The message here is that you can use matplotlib.ticker.FuncFormatter to use any function to obtain a tick label. The function takes two arguments (value and position) and returns a string.

like image 165
Christoph Avatar answered Oct 06 '22 12:10

Christoph


This is an alternative plotting method plot_date, which you might want to use if your independent variable are datetime like, instead of using the more general plot method:

import datetime
data = np.random.rand(24)

#a list of time: 00:00:00 to 23:00:00
times = [datetime.datetime.strptime(str(i), '%H') for i in range(24)]

#'H' controls xticklabel format, 'H' means only the hours is shown
#day, year, week, month, etc are not shown
plt.plot_date(times, data, fmt='H')
plt.setp(plt.gca().xaxis.get_majorticklabels(),
         'rotation', 90)

enter image description here

The benefit of it is that now you can easily control the density of xticks, if we want to have a tick every hour, we will insert these lines after plot_date:

##import it if not already imported
#import matplotlib.dates as mdates
plt.gca().xaxis.set_major_locator(mdates.HourLocator())

enter image description here

like image 34
CT Zhu Avatar answered Oct 06 '22 12:10

CT Zhu