Written and maintained by CASRAI Editorial Board
Last updated
In R, the Breusch-Pagan test is run with bptest() from the lmtest package: pass it a fitted lm object and it returns a chi-squared test of whether the residual variance depends on the model’s regressors. A small p-value is evidence against constant error variance. This page covers the call itself, what each argument does, how to read the returned object, and what to do when it errors. For the logic of the test and a worked interpretation, see the Breusch-Pagan test guide; this page is the R-specific how-to.
What bptest() is used for in research
Ordinary least squares standard errors assume the error variance is the same across observations. bptest() is the diagnostic that checks that assumption after you have fitted a linear model. The package documentation describes the mechanism: the test fits a linear regression to the residuals of the main model, by default using the same explanatory variables, and rejects when those variables explain a substantial share of the residual variance. Under the null hypothesis of constant variance the statistic follows a chi-squared distribution whose degrees of freedom equal the number of regressors excluding the constant.
It belongs alongside a residual plot, not in place of one. See how to read a residual plot for homoscedasticity for the visual check.
Install or access (official source only)
bptest() lives in lmtest, titled “Testing Linear Regression Models” on CRAN. The CRAN package page (checked 2026-10-29) lists version 0.9-40, published 2022-03-21, with Achim Zeileis as maintainer, a source tarball, Windows and macOS binaries, and a reference manual. The package is free and installs the usual way for any CRAN package:
install.packages("lmtest")
library(lmtest)
CRAN package page: https://cran.r-project.org/web/packages/lmtest/index.html.
Step-by-step: run the Breusch-Pagan test in R
The default call
- Fit your linear model with
lm()and keep the fitted object. - Load
lmtestwithlibrary(lmtest). - Pass the fitted object to
bptest().
set.seed(1)
d <- data.frame(x = runif(100, 1, 10))
d$y <- 2 + 0.5 * d$x + rnorm(100, sd = 0.3 * d$x) # error spread grows with x
fit <- lm(y ~ x, data = d)
bptest(fit)
The simulated errors above are built so that their spread rises with x, which is the pattern the test is designed to detect. The package’s own help-page example uses the same idea: one outcome simulated with non-constant error variance and one with constant variance, with the test expected to reject for the first.
The arguments
The usage documented for lmtest 0.9-40 is bptest(formula, varformula = NULL, studentize = TRUE, data = list(), weights = NULL) (RDocumentation page for the package help, checked 2026-10-29).
- formula: the model to test, given either as a model formula or as a fitted
lmobject. - varformula: a one-sided formula naming the variables the variance may depend on. It defaults to the regression model’s own explanatory variables.
- studentize: when
TRUE(the default), Koenker’s studentized version of the statistic is used. Set it toFALSEto use the non-studentized statistic, the original Breusch-Pagan form. - data: an optional data frame holding the model’s variables. If omitted, variables are taken from the calling environment.
- weights: an optional vector of weights for the model.
Testing a specific variance model with varformula
To ask whether the variance depends on particular variables, such as a squared term or a variable left out of the mean model, give varformula a formula with nothing on the left of the tilde:
bptest(fit, ~ x + I(x^2), data = d)
Because the degrees of freedom equal the number of non-constant regressors in the variance model, this call has 2 degrees of freedom, while the default call on y ~ x has 1.
Switching the studentized version off
bptest(fit, studentize = FALSE)
The studentized version is the default and is the one attributed to Koenker (1981) in the documentation. The statsmodels documentation for Python’s equivalent describes the same split: the Koenker version assumes i.i.d. error terms, while the original Breusch-Pagan version assumes normally distributed residuals. If your residuals are visibly non-normal, keep the default.
Output and how to read it
bptest() returns an object of class htest, R’s standard container for a hypothesis test. According to the documentation it holds the test statistic, the degrees of freedom, the p-value, a description of the method, and the name of the data. Printing it shows these in a short block; you can also pull each piece out by name, for example bptest(fit)$p.value.
- Statistic: the chi-squared test statistic. Larger values mean the regressors explain more of the residual variance.
- Degrees of freedom: the number of non-constant regressors in the variance model, which is the model’s own regressors unless you supplied
varformula. - p-value: the probability of a statistic at least this large if the error variance were constant. A small value, below your chosen significance level, is evidence of heteroscedasticity. A large value means the test found no evidence of variance depending on those regressors, which is not proof that the variance is constant. See what a p-value does and does not tell you.
If the test rejects, the usual next step is not to change the coefficients but to change the standard errors. The guide to robust (HC0-HC3) standard errors covers that fix.
Troubleshooting
- Error: could not find function “bptest”. The package is installed but not attached, or not installed. Run
library(lmtest); if that fails with a message that there is no package called lmtest, runinstall.packages("lmtest")first. - Variables not found, or the wrong variables used. When you pass a formula rather than a fitted object,
bptest()takes variables fromdataif you supply it and otherwise from the calling environment. Passdata = your_data_frameso the test does not pick up a same-named object left in your workspace. - varformula errors or gives an unexpected degrees-of-freedom count.
varformulais one-sided. Write~ x1 + x2, noty ~ x1 + x2. The degrees of freedom follow the variables in this formula, not the main model. - Different results across software. Check which version of the statistic each tool runs by default and whether it models the variance on the regressors or on the fitted values (see the table below).
Free alternatives
All three options below are free. The rows follow each tool’s own documentation, checked 2026-10-29.
| Tool | Call | What the documentation says |
|---|---|---|
| R, lmtest | bptest(model) |
Default variance model is the regression’s own explanatory variables; varformula changes it; Koenker’s studentized version by default. |
| R, car | ncvTest(model) |
Score test of constant error variance for a model fitted with lm. If var.formula is omitted, the variance is modelled as depending on the fitted values. The page notes the test is often called the Breusch-Pagan test and was independently suggested, with some extension, by Cook and Weisberg (1983). The glm method reports an error. |
| Python, statsmodels | het_breuschpagan(resid, exog_het, robust=True) |
Takes residuals and the variables suspected of driving heteroscedasticity; returns the LM statistic, its p-value, an F statistic and its p-value. robust=True is Koenker’s version. The documentation notes the LM test may overstate significance in small or moderately large samples, so the F statistic is preferred there. |
The practical difference between the two R functions is the default: bptest() tests against the model’s regressors, ncvTest() against the fitted values, so their p-values need not match.
Frequently asked questions
How do I run a Breusch-Pagan test in R?
Install and load lmtest, fit your model with lm(), and call bptest(fit). The returned p-value tests the null hypothesis of constant error variance.
What is the difference between bptest in R and the Breusch Pagan test?
They are the same test. bptest() is the name of the R function in lmtest that implements the Breusch-Pagan test (Breusch and Pagan 1979), by default in the studentized form attributed to Koenker (1981).
What does a significant bptest result mean?
It is evidence that the residual variance depends on the variables in the variance model, so the default OLS standard errors cannot be relied on. Follow up with a residual plot and with heteroscedasticity-consistent standard errors; see robust standard errors.
Can I use bptest with a model that has weights?
The function has a weights argument, documented as an optional vector of weights for the model.
Where is the broader regression context?
Heteroscedasticity is one of several assumptions to check; the regression analysis guide places it among the others.
Sources
All links checked 2026-10-29.
- CRAN, lmtest: Testing Linear Regression Models, version 0.9-40, package page. https://cran.r-project.org/web/packages/lmtest/index.html.
- RDocumentation, lmtest 0.9-40 help topic for
bptest(usage, arguments, details, value, references). https://www.rdocumentation.org/packages/lmtest/versions/0.9-40/topics/bptest. - RDocumentation, car help topic for
ncvTest(car 3.1-5 as listed). https://www.rdocumentation.org/packages/car/topics/ncvTest. - statsmodels documentation,
statsmodels.stats.diagnostic.het_breuschpagan. https://www.statsmodels.org/stable/generated/statsmodels.stats.diagnostic.het_breuschpagan.html. - Breusch, T.S. and Pagan, A.R. (1979), Econometrica 47, 1287-1294. Koenker, R. (1981), Journal of Econometrics 17, 107-112 (as cited in the lmtest help page).








