Anscombe's Quartet and the Datasaurus Dozen: Why You Plot Your Data First
Anscombe's quartet is four small datasets, published by the statistician F. J. Anscombe in The American Statistician in 1973, that share the same means, variances, correlation, and least-squares line but look completely different when plotted: a noisy line, a curve, a line bent by one outlier, and a vertical stack plus one distant point. The Datasaurus Dozen (Matejka and Fitzmaurice, CHI 2017) makes the same point with 13 datasets, one of them a dinosaur. Both teach one thing: summary statistics throw away the shape of the data, so plot it before you trust a number or fit a model.
Quick answer: Anscombe's quartet (1973) is four datasets of 11 points each that all have mean x = 9, variance x = 11, mean y ≈ 7.50, variance y ≈ 4.12 to 4.13, Pearson correlation r ≈ 0.816, and the regression line y = 3 + 0.5x, yet their scatter plots show a linear trend, a smooth curve, a line pulled by one outlier, and a slope created by a single point. The Datasaurus Dozen (2017) repeats the trick with 13 datasets whose means, standard deviations, and correlation match to two decimal places. The lesson: identical statistics do not mean identical data, so always plot. In Python, seaborn.load_dataset("anscombe") loads the quartet.
What is Anscombe's quartet?
It is a teaching example Francis Anscombe built for his 1973 paper "Graphs in Statistical Analysis." Each of the four datasets, labeled I to IV, has 11 (x, y) pairs. Datasets I, II, and III use the same x values (4 through 14); dataset IV puts ten points at x = 8 and one at x = 19. His argument was that analysts should "make both calculations and graphs. Both sorts of output should be studied; each will contribute to understanding." How he constructed the numbers is not known.
What summary statistics do the four datasets share?
All four agree on the count, both means, both variances, the correlation, and the fitted regression line. The x statistics are identical exactly; the y statistics differ only in the third decimal place. Variances below are sample variances (divided by n − 1), which is what pandas and most statistics software report by default.
| Statistic | Value in all four datasets |
|---|---|
| Number of points (n) | 11 |
| Mean of x | 9 (exact) |
| Sample variance of x | 11 (exact) |
| Mean of y | 7.50 |
| Sample variance of y | 4.12 to 4.13 |
| Standard deviation of y | 2.03 |
| Pearson correlation r | 0.816 (0.817 for dataset IV at three decimals) |
| Least-squares line | y = 3.00 + 0.500x |
| R² | 0.67 |
| Standard error of the slope | 0.118 |
Shown only this table, most analysts would conclude that all four datasets describe the same moderately strong linear relationship. That is true of dataset I and misleading for the other three.
How are the four datasets in Anscombe's quartet different?
Plotted, they tell four different stories, and only one of them fits the straight-line model the shared statistics imply. Robust and rank-based statistics start to separate them: the medians and Spearman rank correlations below differ even though the means and Pearson r do not.
| Dataset | What the scatter plot shows | Median y | Spearman ρ | What the straight-line fit gets wrong |
|---|---|---|---|---|
| I | A noisy linear cloud | 7.58 | 0.82 | Nothing serious; a linear model is reasonable here |
| II | A smooth arch that a quadratic fits almost exactly (R² above 0.9999) | 8.14 | 0.69 | Misses the curvature; residuals are negative at both ends and positive in the middle |
| III | Ten points on a near-perfect line plus one outlier at (13, 12.74) | 7.11 | 0.99 | The outlier tilts the line; without it the fit is y ≈ 4.01 + 0.345x with r above 0.9999 |
| IV | Ten points stacked at x = 8 and one point at (19, 12.50) | 7.04 | 0.50 | One point sets the entire slope; remove it and x has no variance, so no slope can be estimated |
Dataset IV is the one that catches careful analysts. In simple regression, a point's leverage is h = 1/n + (x − x̄)² / Σ(x − x̄)², and for the point at x = 19 that is 1/11 + 100/110 = 1. With leverage 1, the fitted line is forced through the point, so its residual is exactly 0 and a residual plot shows nothing unusual there. Cook's distance divides by (1 − h)², so for that point it is undefined rather than large. Dataset III's outlier is the easy case by comparison: its residual is 3.24 and its Cook's distance is about 1.39, far above any other point in that set.
How do I reproduce Anscombe's quartet in Python with seaborn?
Seaborn ships the quartet as a built-in example dataset in long format: a dataset column with the values I to IV, plus x and y. load_dataset downloads it from the seaborn-data repository on GitHub the first time you call it, so it needs internet access once, then reads from a local cache. This computes the shared statistics for each dataset:
import numpy as np
import pandas as pd
import seaborn as sns
df = sns.load_dataset("anscombe") # columns: dataset (I-IV), x, y
rows = []
for name, g in df.groupby("dataset"):
slope, intercept = np.polyfit(g["x"], g["y"], 1)
rows.append({
"dataset": name,
"mean_x": g["x"].mean(), "var_x": g["x"].var(),
"mean_y": g["y"].mean(), "var_y": g["y"].var(),
"r": g["x"].corr(g["y"]),
"intercept": intercept, "slope": slope,
})
print(pd.DataFrame(rows).set_index("dataset").round(3))
Output:
mean_x var_x mean_y var_y r intercept slope
dataset
I 9.0 11.0 7.501 4.127 0.816 3.000 0.5
II 9.0 11.0 7.501 4.128 0.816 3.001 0.5
III 9.0 11.0 7.500 4.123 0.816 3.002 0.5
IV 9.0 11.0 7.501 4.123 0.817 3.002 0.5
Now plot it. lmplot draws a scatter plot with a fitted regression line in each panel, and the panels share axes by default, which is what makes the comparison fair:
sns.lmplot(data=df, x="x", y="y", col="dataset", col_wrap=2,
ci=None, height=3, scatter_kws={"s": 40})
The four panels show exactly what the comparison table describes: the same fitted line drawn through a linear cloud, an arch, a line with one outlier, and a vertical stack joined to one point. To see the statistics that do separate the sets, compare medians and Spearman correlations. Pearson on ranks is Spearman's ρ, and pandas' default average ranking handles the tied x values in dataset IV:
check = pd.DataFrame({
"median_y": df.groupby("dataset")["y"].median(),
"spearman": [grp["x"].rank().corr(grp["y"].rank())
for _, grp in df.groupby("dataset")],
})
print(check.round(2))
median_y spearman
dataset
I 7.58 0.82
II 8.14 0.69
III 7.11 0.99
IV 7.04 0.50
In R, the quartet is built in as anscombe in the base datasets package, in wide format (x1 to x4, y1 to y4). For more on faceted layouts like the one above, see small multiples charts.
What is the Datasaurus Dozen?
The Datasaurus Dozen is a set of 13 datasets of 142 points each that share the same x mean, y mean, x and y standard deviations, and Pearson correlation to two decimal places: mean x = 54.26, mean y = 47.83, SD x = 16.76, SD y = 26.93, r = −0.06. It accompanies Justin Matejka and George Fitzmaurice's CHI 2017 paper "Same Stats, Different Graphs: Generating Datasets with Varied Appearance and Identical Statistics through Simulated Annealing." The starting point was the Datasaurus, a dinosaur-shaped scatter plot Alberto Cairo created in 2016, which the authors morphed toward 12 target shapes, including a star, a circle, a bullseye, an X, horizontal and vertical lines, and diagonal slants.
The method is what makes it more than a curiosity. Starting from an existing dataset, they repeatedly move a random point by a small amount, keep the move only if the statistics still match to two decimal places, and favor moves that bring points closer to the target shape. Simulated annealing accepts some moves away from the target early on so the process does not get stuck. The technique does not depend on which statistics are held fixed, and the same paper uses it to produce six different distributions that draw an identical boxplot.
| Anscombe's quartet | Datasaurus Dozen | |
|---|---|---|
| Published | 1973, The American Statistician | 2017, ACM CHI conference |
| Created by | F. J. Anscombe | Justin Matejka and George Fitzmaurice, starting from Alberto Cairo's Datasaurus |
| Datasets | 4 | 13 (the dinosaur plus 12 shapes) |
| Points per dataset | 11 | 142 |
| Statistics held equal | Means, variances, correlation, regression line | Means, standard deviations, Pearson correlation (to two decimals) |
| How it was made | Not known | Simulated annealing from the dinosaur toward each target shape |
| Where to get it | seaborn load_dataset("anscombe"); R anscombe | R datasauRus package; not included in seaborn |
How do I plot the Datasaurus Dozen in Python or R?
Seaborn does not include it, so load it from the R datasauRus package, which provides a long-format datasaurus_dozen data frame with dataset, x, and y columns. In Python, read the same data from the tab-separated file in that package's GitHub repository:
import numpy as np
import pandas as pd
import seaborn as sns
url = ("https://raw.githubusercontent.com/jumpingrivers/datasauRus/"
"main/inst/extdata/DatasaurusDozen-Long.tsv")
dd = pd.read_csv(url, sep="\t") # columns: dataset, x, y
stats = dd.groupby("dataset").agg(
mean_x=("x", "mean"), mean_y=("y", "mean"),
sd_x=("x", "std"), sd_y=("y", "std"),
)
stats["r"] = [grp["x"].corr(grp["y"]) for _, grp in dd.groupby("dataset")]
print(np.trunc(stats * 100) / 100) # all 13 rows: 54.26, 47.83, 16.76, 26.93, -0.06
sns.relplot(data=dd, x="x", y="y", col="dataset", col_wrap=4,
height=2.5, s=10)
Note the truncation. The 13 sets agree to within 0.01 on every statistic, but they do not all round to the same value: with .round(2), some rows show 54.27 or −0.07. Truncating to two decimals, as above, reproduces the published figures for all 13. In R:
install.packages("datasauRus")
library(datasauRus)
library(ggplot2)
ggplot(datasaurus_dozen, aes(x = x, y = y)) +
geom_point(size = 0.8) +
facet_wrap(~dataset, ncol = 4)
What do Anscombe's quartet and the Datasaurus teach about exploratory data analysis?
Summary statistics are a lossy compression of the data. Many very different datasets map to the same handful of numbers, so a statistic can confirm what a plot shows but cannot replace it. In practice, that becomes a short checklist to run before you report any correlation or fit any regression:
- Plot every relationship you plan to summarize. A plain x-versus-y scatter plot exposes all four quartet datasets in seconds. With larger data, deal with overplotting first; see scatter plot best practices.
- Read Pearson r as linear association only. The same r = 0.816 describes a noisy line, a near-exact curve, a line bent by one outlier, and a slope created by a single point.
- Check residuals and leverage after fitting. A residuals-versus-fitted plot exposes dataset II's curve and dataset III's outlier; only leverage catches dataset IV. The full set of checks is in linear regression assumptions.
- Compare groups on shared axes. Small multiples with common scales make shape differences visible at a glance.
- Pair means with robust statistics. Medians, quartiles, and rank correlations are cheap and do separate the quartet (see descriptive statistics to check first). The Datasaurus is the reminder that no fixed list of numbers substitutes for looking.
What are the common mistakes when applying Anscombe's lesson?
The quartet is easy to cite and easy to misapply. These are the errors that show up most often in real analyses:
- Concluding the statistics are wrong. They are computed correctly. Mean, variance, and r describe center, spread, and linear association; none of them describes shape, and none claims to.
- Deleting the outlier to "fix" dataset III. Dropping (13, 12.74) makes the line nearly perfect, but whether to drop it depends on whether it is a recording error or a real observation. Investigate first, and report both fits if you cannot tell.
- Screening only residuals. In dataset IV the most influential point has a residual of exactly 0. Large-residual checks miss high-leverage points; check leverage and influence too.
- Overlaying every group in one chart. Four, or thirteen, overlapping point clouds hide the shapes you are trying to compare. Facet them instead.
- Letting facets use independent axes. Per-panel autoscaling can make different data look alike and similar data look different. Seaborn's faceted plots share axes by default; keep that for comparisons.
- Assuming any single plot is enough. Plots summarize too. The Datasaurus paper built six different distributions with identical boxplots, so pair a boxplot with a histogram or strip plot when shape matters.
Pro Tip: Make a leverage check routine before you report a regression, not only a residual check. With statsmodels (import statsmodels.formula.api as smf) and iv = df[df["dataset"] == "IV"], smf.ols("y ~ x", data=iv).fit().get_influence().hat_matrix_diag returns 0.1 for ten points and 1.0 for the point at x = 19. Any leverage near 1 means one observation is deciding the slope on its own, and no residual plot will warn you.