0

I have a function that takes a month and year and I want to set the xticks of a plot to the month and year that is inputted.

For example if user enters 5 as the month and 2019 as the year I want to make the first xtick 5/2018, the second one 6/2018, and so on. If it reaches 12/2018, the next tick should be 1/2019.

My code so far:

def cityPlot(self, year, month):
    myDates = [datetime(int(year), month, 1]
    plt.xticks(np.arange(1,17), myDates.split)

I'm not very familiar with matplotlib so it would be helpful if I could get some pointers on how to tackle this problem.

Matt Hall
  • 7,614
  • 1
  • 23
  • 36
drewster
  • 83
  • 1
  • 8
  • You want to use the datetime directly, don't make this `myDates` thing or try to use `split` on that (`split` is a string method). Check https://stackoverflow.com/questions/5902371/matplotlib-bar-chart-with-dates?rq=1 – Matt Hall Oct 15 '19 at 11:07

1 Answers1

1

There's a couple of ways to do this.

See below for some code:

import matplotlib.pyplot as plt
import numpy as np
import datetime

import click

def make_data():
    Nrain       = 20
    start       = datetime.date(2017,12,1)
    end         = datetime.date(2019,1,1)

    period      = (end-start).days/365
    rainfall    = 30*np.random.rand(Nrain) + 120*(1+np.cos(Nrain/period))

    delta       = (end-start)/Nrain
    dates       = [start + i*delta for i in range(Nrain)]
    return rainfall, dates

def plot_rain(rainfall):
    fig = plt.figure(figsize=(8,6))

    ax = fig.subplots()
    ax.plot(rainfall)
    return fig

def xticks_auto(ax,dates,Nticks=10):
    delta       = (dates[-1]-dates[0])/Nticks
    tick_dates  = [dates[0] + i*delta for i in range(Nticks)]
    x_ticks     = ['{}/{}'.format(d.month,d.year) for d in tick_dates]

    ax.set_xticks([i*len(dates)/Nticks for i in range(Nticks)])
    ax.set_xticklabels(x_ticks)

def xticks_pres(ax,dates,Nticks=10):
    start_m     = click.prompt('Start month', type=int)
    start_y     = click.prompt('Start year', type=int)
    end_m       = click.prompt('End month', type=int)
    end_y       = click.prompt('End year', type=int)

    start       = datetime.date(start_y,start_m,1)
    end         = datetime.date(end_y,end_m,1)
    Nticks      = 10
    delta       = (end-start)/Nticks
    tick_dates  = [start + i*delta for i in range(Nticks)]
    x_ticks     = ['{}/{}'.format(d.month,d.year) for d in tick_dates]

    ax.set_xticks([i*len(dates)/Nticks for i in range(Nticks)])
    ax.set_xticklabels(x_ticks)

make_data() makes some pseudo-rainfall data. If we run some simple code to begin with:

>>> rainfall, dates = make_data()
>>> fig = plot_rain(rainfall)
>>> ax = fig.axes[0]

This generates some data and plots it to a figure:

enter image description here

Note that the x-values are simply the indices of the datapoints. If we run xticks_pres, one can prescribe a start date and end date, and the xticks will be updated:

>>> fig = plot_rain(rainfall)
>>> ax = fig.axes[0]
>>> xticks_pres(ax,dates)
Start month: 
5
Start year: 
2011
End month: 
6
End year: 
2015

enter image description here

To be able to add the date points you need either the length of the dates set, or the length of the rainfall set. If you have the dates set, you might as well use an automatic fill:

>>> fig = plot_rain(rainfall)
>>> ax = fig.axes[0]
>>> xticks_auto(ax,dates,5)

enter image description here

On this last code executution, I overrode the defaults value of 10 for Nticks, specifying that I only want 5 ticks.

I think with these snippets you should be able to do what you want to achieve. If you really want to use user input you can, but for most cases it's easier to simply jiggle the xticks automatically.

Enjoy!

soyapencil
  • 509
  • 4
  • 9
  • Thank you this really helps! – drewster Oct 15 '19 at 17:19
  • I have a quick question, I copied your code but why doesn't the plot pop up? – drewster Oct 18 '19 at 03:33
  • 1
    Hi! It may be to do with your current configuration for plotting. Depending on whether you have interactive mode enabled, are plotting to 'agg' to not display your plots, or a range of other reasons, your plot may not be showing. Simple fix: try typing `fig` if you are using an interpreter, or use `plt.show()`. – soyapencil Oct 18 '19 at 10:01