Skip to main content
Data Science

ARIMAX: How to Forecast Time Series With External Variables

Learn how ARIMAX extends ARIMA with external predictors, understand its parameters and assumptions, and build a forecasting model in Python with statsmodels.
Vinod Chugani's photo
Vinod Chugani
· 9 min read

Explore with AI

ChatGPTClaudePerplexity

Create Your Free Account

Practice and track your progress.

Continue with Google
By continuing, you accept our Terms of Use, our Privacy Policy and that your data is stored in the USA.

Say you're forecasting monthly electricity demand. You've got a solid ARIMA model capturing the series’ autocorrelation and trend. Then a heat wave hits, and your forecast misses by 15%. The series didn't change; the weather did. That's exactly the situation ARIMAX was built for: time series forecasting when outside factors drive as much of the variation as the series' own history.

We'll cover what ARIMAX is, how it differs from ARIMA and SARIMAX, and when it makes sense to use one over the other. We'll also walk through a full Python implementation covering data prep, model fitting, diagnostics, and forecast evaluation, so you can apply what you've learned.

What Is ARIMAX?

ARIMAX stands for AutoRegressive Integrated Moving Average with eXogenous variables. It's an ARIMA model that also accepts external inputs, meaning predictors from outside the target series itself. Examples that come to mind: advertising spend, temperature, promotion flags, interest rates.

The general notation is ARIMAX(p, d, q) with one or more exogenous regressors. The p, d, and q parameters carry the same meaning as in ARIMA: the autoregressive order, degree of differencing, and moving average order. The "X" means you can pass in additional columns that you believe influence the target. One thing worth flagging now: some software packages implement ARIMAX as a regression model with ARIMA errors rather than treating external variables as direct AR inputs. The distinction is subtle mathematically, but it matters for how you interpret coefficients. We'll return to this when we look at the statsmodels output.

How ARIMAX Works

ARIMAX combines two things: the memory of the series itself, and the explanatory power of outside variables.

The AR, I, and MA components

The AR (autoregressive) component uses lagged values of the target series to predict the current value. If last month's sales were high, that matters.

The I (integrated) component differences the series to remove trends or unit roots, making it stationary.

The MA (moving average) component uses past forecast errors to correct for systematic mistakes the model has been making.

Together, these three elements handle a lot of what drives a typical time series: trends, cycles, and autocorrelation in the residuals.

Where exogenous variables come in

Exogenous variables contribute information the series' own history can't supply. If you're forecasting sales, past sales tell you about typical patterns. But a price cut or a competitor entering the market is new information. The model estimates a coefficient for each external predictor while simultaneously accounting for autocorrelation in the errors.

Here's the practical read: if your target series is well-explained by its own past values and you have no reliable outside predictors, plain ARIMA is probably sufficient. But when you know external factors are at play, and when you'll actually have future values of those predictors available, ARIMAX tends to give more accurate forecasts.

ARIMA vs. ARIMAX vs. SARIMAX

SARIMAX builds on SARIMA by adding exogenous variables. In practice, most Python implementations of ARIMAX go through SARIMAX() from statsmodels, with the seasonal order set to zero.

That's not a workaround. It's the standard approach. SARIMAX is a good first choice when your series has a clear seasonal pattern or when you need external regressors; it handles both cleanly. One caveat: "ARIMAX" and "SARIMAX" aren't interchangeable across every library. In some packages, SARIMAX with no seasonal terms and ARIMAX are functionally identical. In others, they differ in how the exogenous variables enter the likelihood. Check the docs for whatever tool you're using.

When to Use ARIMAX

It usually comes down to one thing: do you have external predictors that plausibly influence the target, and will you have their future values when it's time to forecast?

Situations where ARIMAX adds value

Good candidates include sales forecasting with promotion flags or price changes, energy demand with temperature inputs, website traffic with campaign spend, and economic indicators alongside interest rate data. In each case, the external variable provides information the series can't generate on its own.

Plain ARIMA may be sufficient when external predictors are unavailable, unreliable, or simply don't improve out-of-sample accuracy. Adding predictors that introduce noise without signal doesn't help. More inputs don't guarantee better forecasts. Evaluate any proposed predictor on held-out data before committing to it.

A word on causation

A relationship between a predictor and the target doesn't establish causation. ARIMAX is a forecasting framework; it estimates associations. If advertising spend correlates with sales because both go up in December, the model may pick that up, but it won't tell you advertising caused the increase. That distinction matters if you're using forecasts to inform decisions rather than just predict outcomes. It's worth being explicit about this when presenting results.

How to Build an ARIMAX Model in Python

Now for the implementation.

We'll use a reproducible example: monthly ice cream sales (units sold) with temperature (°C) and a promotion flag as exogenous predictors. The dataset spans 48 months, split into 36 months for training and 12 for evaluation.

Prepare the data

Start by loading or constructing a DataFrame with a consistent monthly date index. Identify your target variable and your exogenous columns, then align everything by date. Handle missing values before splitting. Don't impute across the train/test boundary, as that introduces leakage.

The rule to internalize early: whatever exogenous values you pass during training, you'll need equivalent future values at forecast time. If you can't get future temperature forecasts, you can't use temperature as a predictor. That's not a minor footnote; it rules out a lot of candidates.

import pandas as pd
import numpy as np
from statsmodels.tsa.statespace.sarimax import SARIMAX
from statsmodels.tsa.stattools import adfuller
from sklearn.metrics import mean_absolute_error

# Construct a sample monthly dataset
np.random.seed(42)
dates = pd.date_range(start="2020-01", periods=48, freq="MS")
temperature = 15 + 10 * np.sin(np.linspace(0, 4 * np.pi, 48)) + np.random.normal(0, 1, 48)
promotion = np.where((np.arange(48) % 6 == 0), 1, 0)
sales = (
    500
    + 8 * temperature
    + 150 * promotion
    + np.cumsum(np.random.normal(0, 10, 48))
)

df = pd.DataFrame({"sales": sales, "temperature": temperature, "promotion": promotion}, index=dates)

# Train/test split
train = df.iloc[:36]
test = df.iloc[36:]

Scaling isn't usually required for statsmodels estimation, but it helps with numerical stability when predictors are on very different scales. Whether to scale is a judgment call.

Check the series and predictors

Before selecting model parameters, inspect the target series visually and run a stationarity test. The Augmented Dickey-Fuller (ADF) test is standard. A p-value below 0.05 suggests the series is stationary and probably doesn't need differencing (d=0). If the series has a clear trend, you'd typically set d=1. Tests are one input; domain knowledge and visual inspection matter too.

Also check your predictors: are they aligned with the target? Is there any chance a predictor is measured after the forecast date? A promotion flag set before the month starts is fine. Revenue from that month is not.

Choose candidate parameters and fit the model

ACF and PACF plots help suggest candidate values for p and q. A significant spike at lag 1 in the PACF with a tapering ACF often suggests AR(1); the reverse suggests MA(1). Compare a small set of candidates using AIC or BIC on the training data, and save the test set for final evaluation only.

# Fit ARIMAX(1,1,1) via SARIMAX with no seasonal order
exog_train = train[["temperature", "promotion"]]
exog_test = test[["temperature", "promotion"]]

model = SARIMAX(
    train["sales"],
    exog=exog_train,
    order=(1, 1, 1),
    seasonal_order=(0, 0, 0, 0),
    trend="n"
)
result = model.fit(disp=False)
print(result.summary())

The summary() output shows the ARIMA coefficients alongside the exogenous variable coefficients. That temperature coefficient tells you how much a one-degree increase in temperature is associated with a change in the level of sales, after the autoregressive structure accounts for the series’ own momentum. One thing worth knowing: statsmodels uses a regression-with-ARIMA-errors formulation, which means the differencing (d=1) is applied to the error process, not to the regression equation itself. The coefficient represents the effect on the level of sales regardless of d. In a transfer-function ARIMAX formulation (used by some other packages), d=1 would mean coefficients reflect effects on changes rather than levels. That distinction trips people up, so it’s worth checking the docs for whatever tool you’re using.

Check residuals and evaluate forecasts

Residuals should look like white noise. Check the residual ACF plot for any remaining autocorrelation. Significant spikes mean the model is missing structure. If you see systematic patterns at seasonal lags, switch to SARIMAX with a seasonal order.

# Generate out-of-sample predictions
predictions = result.forecast(steps=12, exog=exog_test)

# Evaluate
mae = mean_absolute_error(test["sales"], predictions)

# Naive baseline: forecast each period using the previous period's actual value
naive_forecast = np.concatenate([[train["sales"].iloc[-1]], test["sales"].values[:-1]])
naive_mae = mean_absolute_error(test["sales"], naive_forecast)

print(f"ARIMAX MAE: {mae:.1f}")
print(f"Naive MAE:  {naive_mae:.1f}")

Compare the ARIMAX MAE against a naive baseline (using the previous period's value as the forecast). If ARIMAX doesn't beat the naive model on your test set, that's a meaningful result. The added complexity isn't justified. I've seen this happen more than you'd expect, especially when the exogenous predictors are noisier than they look in-sample.

Forecast future values

Forecasting beyond the training period works the same way as out-of-sample evaluation: supply future exogenous values alongside the forecast() call. For promotion flags, this is usually straightforward since you know the promotional calendar in advance. For temperature, you'd typically use a weather forecast or historical seasonal averages.

Keep this straight: the confidence intervals statsmodels returns are conditional on the predictor values you supply. They don't account for uncertainty in those predictors. If your temperature forecast is uncertain, the actual forecast uncertainty is wider than the intervals suggest. Worth communicating if you're presenting results to anyone who might act on them.

Common Challenges and Limitations

The implementation above covers the happy path. Here's where things tend to break down.

  • Future predictors may be unknown: This is the most common practical barrier. If you can't reliably obtain future values of your exogenous variables, you can't use them. Forecasting energy demand with tomorrow's temperature requires a temperature forecast, not yesterday's.
  • Predictors can leak information: A variable measured after the forecast date can make your in-sample evaluation look far better than it really is. Be careful about what timestamps your predictors actually correspond to.
  • Relationships may change: Coefficients estimated on historical data may not hold going forward. A price elasticity that was stable for two years can shift after a market shock, and 2024 and 2025 produced enough of those to make this feel less theoretical than it used to. Re-estimating the model periodically is good practice.
  • Correlated predictors complicate interpretation: Highly collinear inputs can make individual coefficient estimates unstable. This doesn't always hurt forecast accuracy, but it makes it harder to say which predictor is doing the work.
  • More inputs don't guarantee better forecasts: Evaluate every proposed predictor against a baseline on held-out data. Some features that look informative in-sample add noise out-of-sample.
  • Seasonality needs seasonal terms: If your series has a consistent seasonal pattern, like monthly sales with a December spike, SARIMAX with a seasonal order is the right call. ARIMAX alone won't capture it.
  • Causation is not established: Worth repeating: ARIMAX is a forecasting framework, not a causal inference method. Don't use coefficient signs to make causal claims without additional analysis.

Conclusion

ARIMAX earns its place when you have external factors that genuinely influence the target, and you can supply their future values at forecast time. It's a natural extension of ARIMA, not a replacement. If your series is well-behaved and you don't have reliable predictors, plain ARIMA is usually the better starting point. Adding variables feels like progress. Sometimes it isn't.

The workflow comes down to four things done well:

  1. align your predictors correctly,
  2. check for leakage before evaluating,
  3. validate on genuinely held-out data, and
  4. always compare against a simple baseline.

An ARIMAX model that barely beats a naive forecast is not better than a naive forecast. It's just more expensive.

If you want to go deeper on the time series foundations, our Time Series Analysis in Python course covers ARIMA, stationarity, and diagnostics in detail. For the statsmodels side of things, our Introduction to Regression with statsmodels in Python course builds the statistical intuition you'll want when interpreting model summaries and checking residuals.


Vinod Chugani's photo
Author
Vinod Chugani
LinkedIn

Vinod Chugani began his career in Tokyo as JPMorgan's youngest Hedge Fund Sales Desk Head and later set an individual sales record at Lehman Brothers, then built a 30-country electronics distribution business past SG$100 million in revenue before pivoting to data. A Duke Economics grad and NYC Data Science Academy alum, he was one of three scholarship recipients out of 100+ applicants for Hugo Bowne-Anderson's Building AI Applications course on Maven. Today, he writes for DataCamp, KDnuggets, Machine Learning Mastery, and Statology on topics from statistics to agentic AI, and mentors data professionals at NYC Data Science Academy with over 1,000 one-on-one sessions to his name.

 

FAQs

What is the difference between ARIMAX and ARIMA?

ARIMA forecasts a target series using only its own past values and past forecast errors. ARIMAX extends this by incorporating exogenous variables—external inputs like temperature, promotions, or interest rates—that are believed to influence the target. If those external factors genuinely drive variation in your series and you can supply their future values, ARIMAX will typically produce better forecasts than ARIMA alone.

How does ARIMAX differ from SARIMAX?

ARIMAX handles external variables but not seasonal patterns. SARIMAX adds seasonal AR, differencing, and MA terms on top of ARIMAX, making it the right choice when your series has a recurring seasonal structure. In Python’s statsmodels, ARIMAX is typically implemented via SARIMAX() with the seasonal order set to (0, 0, 0, 0). Functionally, they’re the same model in that configuration.

Do I need to provide future values of exogenous variables to forecast with ARIMAX?

Yes—this is one of the most important practical constraints. When generating forecasts beyond the training period, you must supply values for each exogenous variable at every future time step. For promotion flags or holiday indicators, this is usually straightforward. For variables like temperature or commodity prices, you’ll need forecasted values or reasonable assumptions, which introduces additional uncertainty.

How do I choose p, d, and q for an ARIMAX model?

Start with the ACF and PACF plots of the (differenced) target series. A significant spike at lag 1 in the PACF and a decaying ACF often suggests AR(1); the reverse pattern suggests MA(1). Use domain knowledge and the ADF test to determine d. Then compare a small set of candidate (p, d, q) combinations using AIC or BIC on the training data. Avoid using the test set during this selection step—it should only be used for final evaluation.

What does the coefficient on an exogenous variable mean in an ARIMAX model?

The coefficient represents the estimated change in the level of the target series associated with a one-unit increase in that predictor, after accounting for the autoregressive structure. In statsmodels, this holds even when d=1, because the differencing is applied to the error process rather than to the regression equation (this is the regression-with-ARIMA-errors formulation). Some other packages use a transfer-function formulation where d=1 would make coefficients reflect effects on changes instead of levels, so check the documentation for your tool. Interpretation can also get tricky when predictors are on different scales or are correlated with each other, so it’s worth standardizing inputs when you care about comparing coefficients.

How do I detect and handle multicollinearity in exogenous predictors?

Calculate the Variance Inflation Factor (VIF) for each predictor before fitting. Values above 10 suggest problematic collinearity. If you find it, try removing the least theoretically justified predictor, or combine correlated variables into a single composite. High collinearity won’t necessarily hurt forecast accuracy, but it makes individual coefficients unreliable and hard to interpret.

How should I evaluate whether ARIMAX is actually adding value?

Always compare against a simple baseline—a naïve forecast (using the previous period’s value) is a good starting point. If ARIMAX doesn’t beat it on held-out test data, the model isn’t earning its complexity. MAE and RMSE are both reasonable metrics; MAE is easier to explain to stakeholders. Run the comparison on a proper test set that was never used for parameter selection.

When should I use SARIMAX instead of ARIMAX?

Use SARIMAX when your series shows a consistent seasonal pattern—monthly sales with a December peak, weekly web traffic with a Monday spike, and so on. SARIMAX adds seasonal AR, differencing, and MA components that ARIMAX lacks. Since Python’s statsmodels implements ARIMAX through SARIMAX() anyway, the practical question is just whether to set a non-zero seasonal order. If your residuals show significant autocorrelation at seasonal lags after fitting ARIMAX, that’s a signal to add seasonal terms.

Topics
Data Science

Learn with DataCamp

Course

Forecasting in R

5 hr
52.8K
Learn how to make predictions about the future using time series forecasting in R including ARIMA models and exponential smoothing methods.
See DetailsStart Course

Create Your Free Account

Practice and track your progress.

Continue with Google
By continuing, you accept our Terms of Use, our Privacy Policy and that your data is stored in the USA.
See More
Related

blog

AI Time Series Forecasting: A Beginners' Guide

Learn how AI is transforming time series forecasting through adaptability, uncovering hidden patterns, and handling multiple variables.
Stanislav Karzhev's photo

Stanislav Karzhev

8 min

podcast

The Forecast for Time Series Forecasts with Rami Krispin, Senior Manager of Data Science at Apple

Richie and Rami explore time series foundation models and the case for scaling, feature engineering in the business world, communicating forecast uncertainty to stakeholders, the evolving role of data scientists as architects, and much more.
Richie Cotton's photo

Richie Cotton

53 min

Tutorial

ARIMA for Time Series Forecasting: A Complete Guide

Learn the key components of the ARIMA model, how to build and optimize it for accurate forecasts in Python, and explore its applications across industries.
Zaina Saadeddin's photo

Zaina Saadeddin

12 min

Tutorial

SARIMA: A Complete Guide to Seasonal Time Series Forecasting

Learn how SARIMA extends ARIMA to handle seasonality, understand its seven parameters, and build a working model in Python from data collection through forecasting.
Vinod Chugani's photo

Vinod Chugani

15 min

Tutorial

Time Series Forecasting Tutorial

A detailed guide to time series forecasting. Learn to use python and supporting frameworks. Learn about the statistical modelling involved.
Moez Ali's photo

Moez Ali

15 min

Tutorial

Time Series Analysis using R: Tutorial

Learn Time Series Analysis with R along with using a package in R for forecasting to fit the real-time series to match the optimal model.

Salin Kc

13 min

See More