What Are Holiday Variables and Special Dates?

Special dates, such as holidays, promotions, or significant events, often cause notable deviations from normal patterns in your time series. By incorporating these special dates into your forecasting model, you can better capture these expected variations and improve prediction accuracy.

How to Add Holiday Variables and Special Dates

Step 1: Import Packages

Import the required libraries and initialize the Nixtla client.

import pandas as pd
from nixtla import NixtlaClient
nixtla_client = NixtlaClient(
    api_key='my_api_key_provided_by_nixtla'
)

Step 2: Load Data

We use a Google Trends dataset on “chocolate” with monthly frequency:

df = pd.read_csv('https://raw.githubusercontent.com/Nixtla/transfer-learning-time-series/main/datasets/google_trend_chocolate.csv')
df['month'] = pd.to_datetime(df['month']).dt.to_period('M').dt.to_timestamp('M')

df.head()
monthchocolate
02004-01-3135
12004-02-2945
22004-03-3128
32004-04-3030
42004-05-3129

Step 3: Create a Future Dataframe

When adding exogenous variables (like holidays) to time series forecasting, we need a future DataFrame because:

  • Historical data already exists: Our training data contains past values of both the target variable and exogenous features
  • Future exogenous features are known: Unlike the target variable, we can determine future values of exogenous features (like holidays) in advance

For example, we know that Christmas will occur on December 25th next year, so we can include this information in our future DataFrame to help the model understand seasonal patterns during the forecast period.

Start with creating a future DataFrame with 14 months of dates starting from May 2024.

# Create future Dataframe for adding US holidays
start_date = "2024-05"
dates = pd.date_range(start=start_date, periods=14, freq="ME")

dates = dates.to_period("M").to_timestamp("M")

future_df = pd.DataFrame(dates, columns=["month"])
future_df.tail()
month
92025-02-28 00:00:00
102025-03-31 00:00:00
112025-04-30 00:00:00
122025-05-31 00:00:00
132025-06-30 00:00:00

Step 4: Forecast with Holidays and Special Dates

TimeGPT automatically generates standard date-based features (like month, day of week, etc.) during forecasting. For more specialized temporal patterns, you can manually add holiday indicators to both your historical and future datasets.

Create a Function to Add Date Features

To make it easier to add date features to a DataFrame, we’ll create the add_date_features_to_DataFrame function that takes:

  • A pandas DataFrame
  • A date extractor function, which can be CountryHolidays or SpecialDates
  • A time column name
def add_date_features_to_dataframe(df, date_extractor, time_col="month", freq="ME"):
    # Create a copy of the DataFrame
    df = df.copy()

    # Ensure time column is datetime
    datetime_types = ["datetime64[ns]", "datetime64[us]", "datetime64[ms]"]
    if df[time_col].dtype.name not in datetime_types:
        raise ValueError(
            f"Column '{time_col}' must be datetime type, got {df[time_col].dtype}"
        )

    # Create date range
    dates_range = pd.date_range(
        start=df[time_col].min(), end=df[time_col].max(), freq="D"
    )

    # Get date feature indicators and resample to specified frequency
    features_df = date_extractor(dates_range)
    features = features_df.resample(freq).max()
    features = features.reset_index(names=time_col)

    # Merge with input DataFrame
    result_df = df.merge(features)

    return result_df

Add Holiday Features

To add holiday features, we’ll use the CountryHolidays class to compute US holidays and merge them into the future DataFrame.

from nixtla.date_features import CountryHolidays

us_holidays = CountryHolidays(countries=["US"])

future_df_holidays = add_date_features_to_DataFrame(future_df, us_holidays)

print(f"Future DataFrame shape: {future_df_holidays.shape}")
future_df_holidays.head()
monthUS_New Year’s DayUS_Memorial DayUS_Juneteenth National Independence DayUS_Independence DayUS_Labor DayUS_Veterans DayUS_Thanksgiving DayUS_Christmas DayUS_Martin Luther King Jr. DayUS_Washington’s BirthdayUS_Columbus Day
02024-05-31 00:00:0000000000000
12024-06-30 00:00:0000100000000
22024-07-31 00:00:0000010000000
32024-08-31 00:00:0000000000000
42024-09-30 00:00:0000001000000

This DataFrame now includes columns for each identified US holiday as binary indicators.

Next, add holiday indicators to the historical DataFrame.

df_with_holidays = add_date_features_to_DataFrame(df, us_holidays)

df_with_holidays.tail()
monthchocolateUS_New Year’s DayUS_New Year’s Day (observed)US_Memorial DayUS_Independence DayUS_Independence Day (observed)US_Labor DayUS_Veterans DayUS_Thanksgiving DayUS_Christmas DayUS_Christmas Day (observed)US_Martin Luther King Jr. DayUS_Washington’s BirthdayUS_Columbus DayUS_Veterans Day (observed)US_Juneteenth National Independence DayUS_Juneteenth National Independence Day (observed)
2392023-12-31 00:00:00900000000010000000
2402024-01-31 00:00:00641000000000100000
2412024-02-29 00:00:00660000000000010000
2422024-03-31 00:00:00590000000000000000
2432024-04-30 00:00:00510000000000000000

Now, your historical DataFrame also contains holiday flags for each month.

Finally, forecast with the holiday features.

fcst_df_holidays = nixtla_client.forecast(
    df=df_with_holidays,
    h=14,
    freq="ME",
    time_col="month",
    target_col="chocolate",
    X_df=future_df_holidays,
    model="timegpt-1-long-horizon",
    hist_exog_list=[
        "US_New Year's Day (observed)",
        "US_Independence Day (observed)",
        "US_Christmas Day (observed)",
        "US_Veterans Day (observed)",
        "US_Juneteenth National Independence Day (observed)",
    ],
    feature_contributions=True, # for shapley values
)

fcst_df_holidays.head()

Plot the forecast with holiday effects.

nixtla_client.plot(
    df_with_holidays,
    fcst_df_holidays,
    time_col='month',
    target_col='chocolate',
)

We can then plot the weights of each holiday to see which are more important in forecasting the interest in chocolate. We will use the SHAP library to plot the weights.

For more details on how to use the shap library, see our tutorial on model interpretability.

import shap
import matplotlib.pyplot as plt


def plot_shap_values(ds_column, title):
    shap_df = nixtla_client.feature_contributions
    shap_columns = shap_df.columns.difference(
        ["unique_id", ds_column, "TimeGPT", "base_value"]
    )

    shap_obj = shap.Explanation(
        values=shap_df[shap_columns].values,
        base_values=shap_df["base_value"].values,
        feature_names=shap_columns,
    )

    shap.plots.bar(shap_obj, max_display=len(shap_columns), show=False)

    plt.title(title)
    plt.show()

plot_shap_values(ds_column="month", title="SHAP values for holidays")

The SHAP values reveal that Christmas, Independence Day, and Labor Day have the strongest influence on chocolate interest forecasting. These holidays show the highest feature importance weights, indicating they significantly impact consumer behavior patterns. This aligns with expectations since these are major US holidays associated with gift-giving, celebrations, and seasonal consumption patterns that drive chocolate sales.

Add Special Dates

Beyond country holidays, you can create custom special dates with SpecialDates. These can represent unique one-time events or recurring patterns on specific dates of your choice.

Assume we already have a future DataFrame with monthly dates. We’ll create Valentine’s Day and Halloween as custom special dates and add them to the future DataFrame.

from nixtla.date_features import SpecialDates

# Generate special dates programmatically for the full data range (2004-2025)
valentine_dates = [f"{year}-02-14" for year in range(2004, 2026)]
halloween_dates = [f"{year}-10-31" for year in range(2004, 2026)]

# Define custom special dates - chocolate-related seasonal events
special_dates = SpecialDates(
    special_dates={
        "Valentine_season": valentine_dates,
        "Halloween_season": halloween_dates,
    }
)

# Apply special dates to future data
future_df_special = add_date_features_to_DataFrame(future_df, special_dates)

future_df_special.head()
monthValentine_seasonHalloween_season
02024-05-31 00:00:0000
12024-06-30 00:00:0000
22024-07-31 00:00:0000
32024-08-31 00:00:0000
42024-09-30 00:00:0000

We will also add custom special dates to the historical DataFrame.

# Apply special dates to historical data as well
df_special = add_date_features_to_DataFrame(df, special_dates)

df_special.tail()
monthchocolateValentine_seasonHalloween_season
2392023-12-31 00:00:009000
2402024-01-31 00:00:006400
2412024-02-29 00:00:006610
2422024-03-31 00:00:005900
2432024-04-30 00:00:005100

Now, forecast with the special date features.

fcst_df_special = nixtla_client.forecast(
    df=df_special,
    h=14,
    freq="M",
    time_col="month",
    target_col="chocolate",
    X_df=future_df_special,
    model="timegpt-1-long-horizon",
    feature_contributions=True,
)

Plot the forecast with special date effects.

nixtla_client.plot(
    df_special,
    fcst_df_special,
    time_col='month',
    target_col='chocolate',
)

Examine the feature importance of the special dates.

plot_shap_values(ds_column="month", title="SHAP values for special dates")

The SHAP values reveal that Valentine’s Day has the strongest positive impact on chocolate sales forecasts. This aligns with consumer behavior patterns, as chocolate is a popular gift choice during Valentine’s Day celebrations.

Congratulations! You have successfully integrated holiday and special date features into your time series forecasts. Use these steps as a starting point for further experimentation with advanced date features.