Search code examples
pythonpandasmatplotlibdate-rangexticks

Python area plot: cutomize date x-tick location and label, and the set x-limit


I have to following code:

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

#Area Plot
plt.figure(figsize=(15,5))
x=pd.date_range('1992-1-1','2014-12-31',freq='6MS').strftime("%Y-%m").tolist()
y=np.random.uniform(-3, 3 , len(x))
plt.fill_between(x[1:], y[1:], 0, where=y[1:] >= 0, facecolor='red', interpolate=True, alpha=0.7,label='Up')
plt.fill_between(x[1:], y[1:], 0, where=y[1:] <= 0, facecolor='green', interpolate=True, alpha=0.7,label='Down')
plt.show
#plt.savefig('file')

that makes the following figure enter image description here However, the x-labels are too many and crowded. When I set an x-limit

plt.xlim(["1990-01","2015-1"])

the plot becomes empty and labels disappear, and when I try to change the labels of the xticks

plt.xticks(["1990","1995","2000","2005","2010","2015"])

it does not work as expected and labels are shifted. I have three questions:

(1) How to show x-labels every year or five years?
(2) How to show x-ticks every 6 months or every year?
(3) How to set the xlim from 1993 to 2015 ?


Solution

  • This code works

    import numpy as np
    import pandas as pd
    from datetime import datetime, date, time
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    
    x=pd.date_range('1993-01-01', periods=44, freq='2Q',closed='left')
    y=np.random.uniform(-3, 3 , 44)
    
    
    fig=plt.figure(figsize=(15,5))
    ax=fig.add_subplot(1,1,1)
    
    ax.fill_between(x[0:], y[0:], 0, where=y[0:] >= 0, facecolor='red', interpolate=True, alpha=0.7,label='Up')
    ax.fill_between(x[0:], y[0:], 0, where=y[0:] <= 0, facecolor='green', interpolate=True, alpha=0.7,label='Down')
    
    #[Questions 1 and 2] format the x-ticks and labels
    years = mdates.YearLocator()   # every 1 year
    #years = mdates.YearLocator(5)   # every 5 years
    
    months = mdates.MonthLocator(bymonth=[1,7,13])  # every month
    years_fmt = mdates.DateFormatter('%Y')
    ax.xaxis.set_major_locator(years)
    ax.xaxis.set_major_formatter(years_fmt)
    ax.xaxis.set_minor_locator(months)
    
    #[Question 3]x-axis limit
    Start=1993
    End=2015
    start = datetime(year=Start, month=1, day=1, hour=0)
    end   = datetime(year=End, month=1, day=1, hour=0)
    ax.set_xlim(start,end)
    
    plt.show()
    

    enter image description here