Written and maintained by CASRAI Editorial Board
Last updated
The Box-Ljung test (usually written Ljung-Box test) checks whether a set of autocorrelations of a time series is jointly zero. Researchers use it mostly as a residual diagnostic: after fitting a model such as ARIMA, a significant result says the residuals still carry autocorrelation and the model has not captured all the structure in the data.
What the Box-Ljung test is (Ljung-Box test, Box-Pierce test, portmanteau test)
The Ljung-Box test is a portmanteau test: it combines the sample autocorrelations at lags 1 through m into a single statistic instead of judging each lag separately. The NIST/SEMATECH e-Handbook of Statistical Methods states the hypotheses as H0: the model does not exhibit lack of fit, against Ha: the model exhibits lack of fit. In practice, for residuals, a small p-value points to leftover autocorrelation.
Is it Box-Ljung or Ljung-Box?
Both names refer to the same test. It comes from Ljung and Box (1978), “On a Measure of Lack of Fit in Time Series Models,” published in Biometrika. The older Box-Pierce test is from Box and Pierce (1970), published in the Journal of the American Statistical Association. Software documentation (R, statsmodels) offers both under one function and uses the name “Ljung-Box”; “Box-Ljung” is the same procedure with the authors’ names in the other order.
Box-Ljung test formula
The NIST handbook gives the statistic as:
Q = n(n + 2) × Σ rk2 / (n − k), summed over k = 1, 2, …, m.
- Q: the test statistic.
- n: the length of the series (for model residuals, the number of residuals).
- m: the number of lags included in the test.
- rk: the estimated autocorrelation of the series at lag k.
You reject H0 at significance level α when Q is larger than the chi-square critical value with h degrees of freedom at the 1 − α quantile. On a raw series h = m. When the test is applied to the residuals of a fitted ARMA(p, q) model, NIST gives h = m − p − q.
Worked example with the arithmetic shown
This is an illustrative calculation with made-up autocorrelations, not data from a real study. Suppose a series has n = 60 observations and you test m = 5 lags with these sample autocorrelations:
| Lag k | rk | rk2 | n − k | rk2 / (n − k) |
|---|---|---|---|---|
| 1 | 0.31 | 0.0961 | 59 | 0.001629 |
| 2 | −0.12 | 0.0144 | 58 | 0.000248 |
| 3 | 0.18 | 0.0324 | 57 | 0.000568 |
| 4 | 0.05 | 0.0025 | 56 | 0.000045 |
| 5 | −0.09 | 0.0081 | 55 | 0.000147 |
- Sum the last column: 0.001629 + 0.000248 + 0.000568 + 0.000045 + 0.000147 = 0.002637.
- Compute n(n + 2) = 60 × 62 = 3,720.
- Q = 3,720 × 0.002637 = 9.81.
If the 60 values are a raw series (h = 5): the 5% critical value of chi-square with 5 df is 11.07 and the p-value is 0.081. Q is below the critical value, so you do not reject H0 at α = 0.05.
If the 60 values are residuals of an ARMA(1,1) model (p + q = 2, so h = 5 − 2 = 3): the 5% critical value with 3 df is 7.81 and the p-value is 0.020. The same Q now exceeds the critical value, so you reject H0: the residuals still show autocorrelation. The decision flips only because of the degrees-of-freedom adjustment, which is why it matters.
Degrees of freedom for model residuals
Subtract the number of fitted ARMA parameters from the lag count. The three references describe this in different words:
| Source | How the adjustment is expressed |
|---|---|
| NIST/SEMATECH e-Handbook | h = m − p − q for residuals of an ARMA(p, q) model |
R, stats::Box.test |
argument fitdf: degrees of freedom to subtract for a series of residuals; for ARMA residuals set fitdf = p + q, provided lag > fitdf |
Python, statsmodels acorr_ljungbox |
argument model_df; the degrees of freedom are lags − model_df, and NaN is returned if lags − model_df ≤ 0 |
The practical trap: if you test as many lags as the model has parameters (or fewer), there are no degrees of freedom left, and statsmodels returns NaN for the p-value. Test more lags than p + q.
Ljung-Box vs Box-Pierce test
The statsmodels documentation states that the Box-Pierce and Ljung-Box statistics differ in how they scale the autocorrelation function, and that the Ljung-Box test has better finite-sample properties. This is why Ljung-Box is the usual choice of the two. Software switches between the two: R uses type = "Box-Pierce" or type = "Ljung-Box" in Box.test, and statsmodels adds Box-Pierce columns (bp_stat, bp_pvalue) when you pass boxpierce=True.
Interpreting the Ljung-Box p-value
| Result | What it means |
|---|---|
| p ≥ α (Q at or below the critical value) | H0 is not rejected: no evidence of lack of fit, so the tested autocorrelations are consistent with zero. For a model, this is what you hope to see in the residuals. |
| p < α (Q above the critical value) | H0 is rejected: the model exhibits lack of fit, meaning autocorrelation remains in the series or residuals up to lag m. |
A non-significant result does not prove the residuals are independent; it only reports that the first m autocorrelations were not jointly distinguishable from zero. For the surrounding workflow, see the ARIMA modeling guide, where this test is a diagnostic step, and the guide on autocorrelation in time series data. For a test aimed at first-order residual autocorrelation in regression, see the Durbin-Watson test. The statistic is compared with a chi-square distribution and read like any other p-value.
Assumptions and common mistakes
- Forgetting the degrees-of-freedom adjustment. Applying the test to ARMA residuals with h = m instead of m − p − q can change the decision, as the worked example shows (p = 0.081 against 0.020).
- Testing too few lags. In R,
lagmust exceedfitdf; in statsmodels, lags ≤ model_df returns NaN. - Missing values. The R documentation states that missing values are not handled, so remove or impute them before testing.
- Treating a software default as a rule. statsmodels defaults to min(10, nobs // 5) lags when you give none (or min(2 × period, nobs // 5) when a seasonal period is set). That is a default of the function, not a universal recommendation; state the lag you used and why.
- Running it on the wrong object. The test described by NIST is applied to the residuals after fitting the model; applying it to a raw, trending series mostly tells you the series is autocorrelated, which you already knew.
How to report the Ljung-Box test
Report the statistic, the degrees of freedom actually used, the number of lags and the p-value, and say what the test was applied to. An example sentence based on the worked example above (illustrative values):
A Ljung-Box test on the ARMA(1,1) residuals indicated remaining autocorrelation, Q(3) = 9.81, p = .020, using 5 lags.
Give the model order alongside the test so readers can check that the degrees of freedom equal lags minus p minus q.
How to calculate the Ljung-Box test in R, Python and Excel
R
# fit is an ARMA(p, q) model, here p = 1 and q = 1
Box.test(residuals(fit), lag = 10, type = "Ljung-Box", fitdf = 2)
The returned parameter is the degrees of freedom of the approximate chi-square distribution, with fitdf taken into account (here 10 − 2 = 8).
Python (statsmodels)
import statsmodels.api as sm
# res is a fitted ARIMA(1, 0, 1) result
sm.stats.acorr_ljungbox(res.resid, lags=[10], model_df=2, return_df=True)
# columns: lb_stat, lb_pvalue (add boxpierce=True for bp_stat, bp_pvalue)
Excel
Excel has no built-in Ljung-Box function, so compute Q from your autocorrelations and then get the p-value. With lags 1 to m in A2:A6, the autocorrelations in B2:B6 and n in D1:
Q: =D1*(D1+2)*SUMPRODUCT(B2:B6^2/(D1-A2:A6))
p-value: =CHISQ.DIST.RT(Q, df)
critical: =CHISQ.INV.RT(0.05, df)
For the worked example, =CHISQ.DIST.RT(9.81, 5) gives 0.081 and =CHISQ.DIST.RT(9.81, 3) gives 0.020. Set df to m for a raw series or m − p − q for ARMA residuals.
FAQ
What does a significant Ljung-Box test mean?
It means H0 is rejected: the series or residuals show autocorrelation up to the lags tested. For model residuals, that is evidence of lack of fit.
What is the null hypothesis of the Ljung-Box test?
Per NIST, H0 is that the model does not exhibit lack of fit; for residuals this corresponds to no autocorrelation at the tested lags.
What is the difference between the Ljung-Box and Box-Pierce tests?
They scale the autocorrelations differently; the statsmodels documentation notes that the Ljung-Box test has better finite-sample properties.
How many degrees of freedom does the test have?
m on a raw series; m − p − q on the residuals of an ARMA(p, q) model.
Sources
- NIST/SEMATECH e-Handbook of Statistical Methods, Box-Ljung test page, itl.nist.gov/div898/handbook/pmc/section4/pmc4481.htm (checked 2026-10-29).
- R documentation,
stats::Box.test, stat.ethz.ch/R-manual/R-devel/library/stats/html/box.test.html (checked 2026-10-29). - statsmodels documentation,
acorr_ljungbox, statsmodels.org/stable/generated/statsmodels.stats.diagnostic.acorr_ljungbox.html (checked 2026-10-29). - Ljung, G. M. and Box, G. E. P. (1978). On a Measure of Lack of Fit in Time Series Models. Biometrika. Box, G. E. P. and Pierce, D. A. (1970). Distribution of Residual Autocorrelations in Autoregressive-Integrated Moving Average Time Series Models. Journal of the American Statistical Association. Both are listed in the references of the R documentation for Box.test.








