'Python mdates.YearLocator in seaborn plot not working for monthly data

I am plotting a seaborn graph with dates on the x-axis. What I would like to achieve is having yearly tickers on the x-axis. When I use daily data, I do not have a problem. However, when I use monthly data, the last line of code ax1.xaxis.set_major_locator(mdates.YearLocator(base = 1)) only displays the first year (zooms in on the graph). Any help is appreciated!

Here is the daily plot code and final plot:

import numpy as np
import pandas as pd
import math
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.dates as mdates
import matplotlib.ticker as ticker
from datetime import datetime, timedelta

# producing the data
date_today = datetime.now()
days = pd.date_range(date_today, date_today + timedelta(9125), freq='D')
np.random.seed(seed=1111)

data_a = np.random.uniform(-0.005, 0.2, size=len(days))
data_b = np.random.uniform(-0.001, 0.1, size=len(days))

a = pd.DataFrame({'date': days, 'a': data_a})
a = a.set_index('date')
a = a.astype({'a':'float'})

b = pd.DataFrame({'date': days, 'b': data_b})
b = b.set_index('date')
b = b.astype({'b':'float'})

# result dataframe which will be used for the plotting
result = pd.concat([a, b], axis=1)

# make sure only the dates are being used
result = result.reset_index()
result['date'] = result['date'].dt.date
result = result.set_index('date')

# set-up for the plot
matplotlib.rc_file_defaults()
sns.set_style(style=None, rc=None)
fig, ax1 = plt.subplots(figsize=(12,6))
ax2 = ax1.twinx()

# reset index for result
result_date = result.reset_index()

# bar plot
b_plot = sns.barplot(data = result_date, x=result_date.iloc[:, 0], y=result_date.iloc[:, 2], ax=ax1)

# lineplot
result_date['rank'] = result_date['date'].rank(method='dense') - 1
a_plot = sns.lineplot(data=result_date, x='rank', y=result_date.iloc[:, 1], ax=ax2)

# remove the extra margins
ax1.margins(x=0)

# set the x tickers
ax1.set_xticklabels(result_date.date.apply(lambda x: str(x.strftime('%y'))))
ax1.xaxis.set_major_locator(mdates.YearLocator(base = 1))

enter image description here

Here is the monthly data code and plot:

import numpy as np
import pandas as pd
import math
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.dates as mdates
import matplotlib.ticker as ticker
from datetime import datetime, timedelta

# producing the data
date_today = datetime.now()
days = pd.date_range(date_today, date_today + timedelta(9125), freq='M')
np.random.seed(seed=1111)

data_a = np.random.uniform(-0.005, 0.2, size=len(days))
data_b = np.random.uniform(-0.001, 0.1, size=len(days))

a = pd.DataFrame({'date': days, 'a': data_a})
a = a.set_index('date')
a = a.astype({'a':'float'})

b = pd.DataFrame({'date': days, 'b': data_b})
b = b.set_index('date')
b = b.astype({'b':'float'})

# result dataframe which will be used for the plotting
result = pd.concat([a, b], axis=1)

# make sure only the dates are being used
result = result.reset_index()
result['date'] = result['date'].dt.date
result = result.set_index('date')

# set-up for the plot
matplotlib.rc_file_defaults()
sns.set_style(style=None, rc=None)
fig, ax1 = plt.subplots(figsize=(12,6))
ax2 = ax1.twinx()

# reset index for result
result_date = result.reset_index()

# bar plot
b_plot = sns.barplot(data = result_date, x=result_date.iloc[:, 0], y=result_date.iloc[:, 2], ax=ax1)

# lineplot
result_date['rank'] = result_date['date'].rank(method='dense') - 1
a_plot = sns.lineplot(data=result_date, x='rank', y=result_date.iloc[:, 1], ax=ax2)

# remove the extra margins
ax1.margins(x=0)

# set the x tickers
ax1.set_xticklabels(result_date.date.apply(lambda x: str(x.strftime('%y'))))
ax1.xaxis.set_major_locator(mdates.YearLocator(base = 1))

enter image description here



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source