Heteroskedasticity Explained: Meaning, Detection and Fixes, with Real Data

Home › Research Methodology › Heteroskedasticity Explained

Quick answerHeteroskedasticity means the spread of values (or of a regression’s errors) is not constant: it grows or shrinks along with another variable. Its opposite, homoskedasticity, means the spread stays the same. It matters because many tests, including standard regression, assume constant spread; when it is violated, p-values and confidence intervals can be wrong.

Below, we explain heteroskedasticity in plain language and show it clearly in real data from ScholarsColab.

Homoskedasticity vs heteroskedasticity at a glance

Homoskedasticity Heteroskedasticity
Spread of values The same everywhere Changes with another variable
On a scatter plot An even band of points A funnel or fan shape
Everyday example Daily rainfall error of a good gauge Spending varies more among high earners than low earners
Effect on regression Standard errors are correct Standard errors, p-values and intervals can be wrong

Worked example: does the h-index vary more over a research career?

We detect and fix heteroskedasticity in a real regression, notebook-style. Every result is calculated live, and you can run the same code yourself.

The data: one row per ScholarsColab mentor with at least five dated papers, giving their discipline, career length, number of papers, h-index and total citations. The file is anonymised: no names or identifiers, rows are shuffled and citation totals are rounded.

Step 1: Load the data

In [1]:
import numpy as np
import pandas as pd
from datetime import date

# The ScholarsColab Research Methods Index (mentors level): anonymised, updated daily
DATA = "https://scholarscolab.in/wp-json/scholarscolab/v1/research-methods-data?level=mentors"
mentors = pd.read_csv(DATA, comment="#")   # lines starting with # hold the citation

def p_text(p):
    return "< 0.001" if p < 0.001 else f"= {p:.3f}"

print(mentors.shape)
mentors.head()
Out [1]:
(891, 6)
disciplinefirst_yearcareer_yearspapersh_indextotal_citations
0Engineering & computer science20141381680
1Medicine & health20091845460
2Engineering & computer science20151297550
3Engineering & computer science19982910010029550
4Medicine & health2020737252510

Step 2: Fit a regression and plot its residuals

We regress h-index on career length (years since a researcher’s first paper), then plot each residual (actual minus predicted) against the predicted value.

In [2]:
import statsmodels.formula.api as smf
import matplotlib.pyplot as plt

model = smf.ols("h_index ~ career_years", data=mentors).fit()
print(f"h_index = {model.params['Intercept']:.2f} + {model.params['career_years']:.3f} × career_years")

fig, ax = plt.subplots(figsize=(8, 4.5))
ax.scatter(model.fittedvalues, model.resid, s=12, alpha=0.4)
ax.axhline(0, color="grey")
ax.set_xlabel("Fitted h-index")
ax.set_ylabel("Residual")
plt.show()
Out [2]:
h_index = 3.80 + 0.425 × career_years
Scatter plot-304-6101816422166279033Fitted h-indexResidual
Each dot is one mentor: the difference between their actual h-index and the h-index predicted from career length.
How to read it: among mentors with lower predicted h-index (mostly shorter careers) the residuals have a standard deviation of 7.1; among those with higher predicted values it is 13.4. The dots fan out from left to right: the funnel shape of heteroskedasticity.

Step 3: Confirm it with a table

In [3]:
bands = pd.cut(mentors["career_years"], [0, 5, 10, 15, 20, 30, 70],
               labels=["1–5", "6–10", "11–15", "16–20", "21–30", "31+"])
mentors.groupby(bands, observed=True)["h_index"].agg(["count", "median", "std"]).round(1)
Out [3]:
countmedianstd
1–51163.02.7
6–101725.06.0
11–152647.08.9
16–201569.010.1
21–309815.017.3
31+8513.015.4
The standard deviation of the h-index grows from 2.7 for the shortest careers to as much as 17.3, about 6.3 times larger. The spread is clearly not constant.

Step 4: Test it formally

In [4]:
from statsmodels.stats.diagnostic import het_breuschpagan
lm, lm_p, f, f_p = het_breuschpagan(model.resid, model.model.exog)
print(f"Breusch-Pagan test: LM = {lm:.1f}, p {p_text(lm_p)}")
Out [4]:
Breusch-Pagan test: LM = 35.8, p < 0.001

The Breusch-Pagan test checks whether the size of the residuals depends on the predictors. The p-value is < 0.001, so the test confirms heteroskedasticity: the size of the residuals depends on career length.

Step 5: Fix the standard errors

In [5]:
robust = smf.ols("h_index ~ career_years", data=mentors).fit(cov_type="HC3")
print(f"Ordinary standard error of the slope: {model.bse['career_years']:.4f}")
print(f"Robust (HC3) standard error:          {robust.bse['career_years']:.4f}")
Out [5]:
Ordinary standard error of the slope: 0.0316
Robust (HC3) standard error:          0.0434
The robust (HC3) standard error is 37% larger than the ordinary one. Ordinary standard errors assume a constant spread, so here they are too small, making results look more certain than they are. Robust standard errors allow for the changing spread.
Run this analysis yourself. Download the notebook and open it in Jupyter or Google Colab (File → Upload notebook). It loads the same anonymised ScholarsColab data, so your results will match this page.Download notebook (.ipynb) →Data files: papers.csv · mentors.csv

How to detect and fix heteroskedasticity

  1. Plot the residuals of your regression against the predicted values; a funnel shape is the classic sign.
  2. Use a formal test if needed: Breusch-Pagan or White’s test.
  3. Transform the outcome (for example, log or square root) when the spread grows with the size of values.
  4. Use heteroskedasticity-robust standard errors (also called White or HC standard errors).
  5. Consider a better-suited model, such as weighted least squares or a count model for count data.

Common mistakes reviewers point out

  • Never checking the residuals of a regression.
  • Reporting ordinary standard errors when heteroskedasticity is obvious.
  • Removing high values as “outliers” when they are a genuine part of the pattern.
  • Confusing heteroskedasticity with non-linearity; both can appear in residual plots and need different fixes.

Frequently asked questions

What is heteroskedasticity in simple terms?

It means the spread of values or errors is not constant: for example, it gets larger as another variable increases.

Why is heteroskedasticity a problem?

Standard regression assumes errors have the same spread everywhere. When they do not, standard errors, p-values and confidence intervals can be misleading, even though the coefficients themselves may be unbiased.

How do you test for heteroskedasticity?

Plot residuals against predicted values, and use tests such as the Breusch-Pagan test or White’s test.

How do you fix heteroskedasticity?

Common fixes are transforming the outcome (for example, taking logs), using robust standard errors, or using weighted least squares.

Is it heteroskedasticity or heteroscedasticity?

Both spellings are correct and mean the same thing; “heteroscedasticity” is more common in statistics, “heteroskedasticity” in economics.

Use this data in your own work

Use this data in your own research. Download the aggregated figures behind these charts (counts, medians and shares by type of paper, period, method and discipline) as a CSV file. Please cite it as:ScholarsColab (2026). ScholarsColab Research Methods Index [Data set]. Vidhilekha Soft Solutions Pvt Ltd. Retrieved 15 October 2026, from https://scholarscolab.in/research-methodology/. Licensed under CC BY 4.0.Download the data (CSV) →

More research methodology guides

About the data on this page. The ScholarsColab Research Methods Index is built from the Google Scholar publication lists of PhD researchers who mentor on ScholarsColab, and is updated daily as mentors and publications are added. Methods, designs and paper types are identified from titles, so papers whose titles do not mention them are not counted in those groups. The mentors are not a random sample of all researchers (engineering and computer science are strongly represented), so the figures describe this group of researchers and may not apply to research as a whole.