Search code examples
pythonpandasmatplotlibdatetimeseaborn

Changing x axis datetime limits in Seaborn barplot


I am trying to make a barplot in Seaborn, but I am struggling to set the x axis limits. I have data for a set range, but I want to set the x axis limits to a larger range than that! When I try to set the x axis limits, the entire plot disappears! Here is a small reproducible example. Creating a dataframe:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
df = pd.Series([np.random.normal()**2 for x in range(7)], 
        pd.date_range(start = "2024-01-01", end = "2024-01-07"))

And trying to create a barplot:

import matplotlib.dates as mdates
date_rng = pd.date_range(start = "2024-01-01", end = "2024-01-10")

date_range_mpl = mdates.date2num(date_rng)
x_vals = mdates.date2num(df.index)

fig, ax = plt.subplots(figsize = (8,4))
sns.barplot(x = x_vals, y = df.values, ax = ax)
ax.set_xlim(date_range_mpl[0] - 1, date_range_mpl[-1] + 1)

The plot breaks at the last line, when trying to set the x axis limits.

The reason for the mdates.date2num function, is that apparently Seaborn isn't that compatible with pandas datetime objects, so I was recommended to convert these objects to matplotlib's datetime objects (which are just floats) first. I can't figure out why this isn't working! Any help would be greatly appreciated, thank you.

EDIT: To show what I am aiming for, please see the following non-seaborn example:

from datetime import timedelta
date_rng = pd.date_range(start = "2024-01-01", end = "2024-01-10")
fig, ax_al = plt.subplots(figsize = (8,4))

plt.bar(x = df.index, height = df.values)
ax_al.set_xlim([date_rng[0] - timedelta(days = 1), date_rng[-1] + timedelta(days = 1)])

Solution

  • The x-values for a barplot are integers starting from 0.

    One approach is df.reindex(), something like:

    date_rng = (date_rng.union(date_rng + 1 * date_rng.freq)
                        .union(date_rng - 1 * date_rng.freq))
    
    fig, ax = plt.subplots(figsize = (8,4))
    sns.barplot(df.reindex(date_rng), ax=ax)
    fig.autofmt_xdate()
    

    Output:

    enter image description here