Skip to main content
v2026.11,858 entries · CC-BY 4.0

bptest() in R: Running and Reading the Breusch-Pagan Test with lmtest

Run bptest() from lmtest on an lm object, set varformula and studentize, read the htest output, and fix common errors, with free alternatives.

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

  1. Fit your linear model with lm() and keep the fitted object.
  2. Load lmtest with library(lmtest).
  3. 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 lm object.
  • 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 to FALSE to 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, run install.packages("lmtest") first.
  • Variables not found, or the wrong variables used. When you pass a formula rather than a fitted object, bptest() takes variables from data if you supply it and otherwise from the calling environment. Pass data = your_data_frame so the test does not pick up a same-named object left in your workspace.
  • varformula errors or gives an unexpected degrees-of-freedom count. varformula is one-sided. Write ~ x1 + x2, not y ~ 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.

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about bptest() in R: Running and Reading the Breusch-Pagan Test with lmtest

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Ask CASRAI · Regulatory Radar

Research-admin question? Get an answer that links its sources.

An AI assistant specialized in research administration. Every answer links its sources to check before you act. 2 questions free, no account. $29/month after.

  • Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.
  • Every answer numbers its sources and links each one, so you can check the source yourself.