9

My matplotlib pyplot has too many xticks - it is currently showing each year and month for a 15-year period, e.g. "2001-01", but I only want the x-axis to show the year (e.g. 2001).

The output will be a line graph where x-axis shows dates and the y-axis shows the sale and rent prices.

# Defining the variables
ts1 = prices['Month'] # eg. "2001-01" and so on
ts2 = prices['Sale'] 
ts3 = prices['Rent'] 

# Reading '2001-01' as year and month
ts1 = [dt.datetime.strptime(d,'%Y-%m').date() for d in ts1]

plt.figure(figsize=(13, 9))
# Below is where it goes wrong. I don't know how to set xticks to show each year. 
plt.xticks(ts1, rotation='vertical')
plt.xlabel('Year')
plt.ylabel('Price')
plt.plot(ts1, ts2, 'r-', ts1, ts3, 'b.-')
plt.gcf().autofmt_xdate()
plt.show()
divyaSharma
  • 133
  • 2
  • 11
Coloane
  • 319
  • 1
  • 4
  • 12

2 Answers2

11

Try removing the plt.xticks function call altogether. matplotlib will then use the default AutoDateLocator function to find the optimum tick locations.

Alternatively if the default includes some months which you don't want then you can use matplotlib.dates.YearLocator which will force the ticks to be years only.

You can set the locator as shown below in a quick example:

import matplotlib.pyplot as plt
import matplotlib.dates as mdate
import numpy as np
import datetime as dt

x = [dt.datetime.utcnow() + dt.timedelta(days=i) for i in range(1000)]
y = range(len(x))

plt.plot(x, y)

locator = mdate.YearLocator()
plt.gca().xaxis.set_major_locator(locator)

plt.gcf().autofmt_xdate()

plt.show()

enter image description here

Ffisegydd
  • 51,807
  • 15
  • 147
  • 125
7

You can do this with plt.xticks.

As an example, here I have set the xticks frequency to display every three indices. In your case, you would probably want to do so every twelve indices.

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(10)
y = np.random.randn(10)

plt.plot(x,y)
plt.xticks(np.arange(min(x), max(x)+1, 3))
plt.show()

In your case, since you are using dates, you can replace the argument of the second to last line above with something like ts1[0::12], which will select every 12th element from ts1 or np.arange(0, len(dates), 12) which will select every 12th index corresponding to the ticks you want to show.

Pythontology
  • 1,494
  • 2
  • 12
  • 15
  • 1
    min and max do not seem to work on dates. Do you have any advice on how I can turn "1999-01" as min and "2014-06" as max? – Coloane Aug 13 '14 at 07:19
  • Could you try using the indices of the dates instead? Try using `np.arange(0, len(dates), 12)`. – Pythontology Aug 13 '14 at 07:24
  • 1
    You could also do something like `plt.xticks(ts1[0::12])`. (See (here)[http://stackoverflow.com/questions/1403674/pythonic-way-to-return-list-of-every-nth-item-in-a-larger-list] for an example of the behavior of the double-colon selector.) – Pythontology Aug 13 '14 at 07:27
  • It would be nice to know why this was downvoted so that I may improve my answer. Thanks! – Pythontology Aug 13 '14 at 07:49
  • I downvoted it because you provided extra detail in the comments that hasn't been edited into the answer itself (meaning people will need to read through comments (which may be deleted) to understand everything). If you edit the detail in I'll gladly reverse it (though I do disagree with your method and (obviously :P) prefer my own). Sorry it took me a while to reply but was commuting to work. – Ffisegydd Aug 13 '14 at 08:07
  • I fixed my answer -- thanks for the input. I'm kind of new to SO, and appreciate the feedback :) – Pythontology Aug 13 '14 at 08:56