# Scatter plot
## Microsim
### Live player
<div class="microsim-player">
<iframe src="https://editor.p5js.org/sciencenibber/full/YMRNODfOn" width="100%" height="620" frameborder="0" sandbox="allow-scripts allow-same-origin"></iframe>
</div>
<div class="microsim-fallback">
<img src="Microsims/thumbs/Scatter_plot.png" alt="Scatter_plot microsim poster" style="width:100%;border:1px solid #4445;border-radius:6px;">
<p><em>Live microsim (desktop) · <a href="https://editor.p5js.org/sciencenibber/sketches/YMRNODfOn">open sketch in the p5.js editor</a></em></p>
</div>
**Editor URL:** https://editor.p5js.org/sciencenibber/sketches/YMRNODfOn
**Description (100 words):**
A reference Pattern-A composition for a scatter chart: chart frame plus two linear scale closures plus the canonical `glyphDot` primitive emitted once per row. Forty hand-tuned `(x, y)` observations spread around a noisy linear relationship so the cloud has a recoverable trend. Three encoding toggles run from the keyboard — `T` for the least-squares regression line, `C` for category color via an Okabe-Ito palette, `S` for marker size by the weight channel. The HUD shows `n`, the means, the Pearson `r`, and the live regression equation `y_hat = m * x + b`. A hover tooltip names the point under the cursor.
```js
// =============================================================================
// Scatter_plot -- Visualization room microsim
// -----------------------------------------------------------------------------
// ARTICLE : Scatter_plot
// Room : Visualization (the V in GENERATIVE)
// Pattern : Pattern A composition -- Statistical chart types
// Wikitube URL : en.wikitube.io/wiki/Scatter_plot
//
// What this sketch is
// -------------------
// The canonical Pattern-A composition for a scatter chart: a chart frame,
// a pair of linear scale closures, and a single glyph -- the dot -- emitted
// once per data row. The synthetic dataset of forty points is drawn from a
// noisy linear relationship between x and y so the cloud has a visible
// trend the optional regression line can recover. Two extra channels
// (point category and point weight) drive the optional color and size
// encodings.
//
// Parameter table (keyboard-driven so the canvas stays clean of DOM clutter)
// -------------------------------------------------------------------------
// trendOn : boolean -- toggle the least-squares regression line + r
// colorOn : boolean -- toggle category coloring (Tableau-10 style)
// sizeOn : boolean -- toggle size encoding by the weight channel
//
// Layout (Betterfire HUD)
// -----------------------
// TL : title (ARTICLE) + Wikitube URL on the row below
// TR : control hints (T trend C color S size)
// BL : readouts (n, x mean, y mean, Pearson r)
// BR : equation text (the regression model y_hat = m*x + b)
// =============================================================================
const ARTICLE = "Scatter_plot";
p5.disableFriendlyErrors = true; // FES off -- the Betterfire standard
// ----- canonical Visualization palette (light background, ink-on-paper) -----
const BG = 250;
const FG = 24;
const AXIS = [ 80, 90, 110];
const GRID = [200, 205, 215];
const MUTED = [140, 150, 165];
const INK = [ 40, 48, 60];
const DOT_C = [ 70, 130, 200]; // canonical scatter dot blue
const DOT_HI = [220, 110, 60]; // contrast color for the hovered dot
const TREND_C = [ 60, 180, 90]; // green trend line
// Categorical palette (Okabe-Ito subset, perceptually distinct)
const CAT_C = [
[ 0, 114, 178], // 0 blue
[230, 159, 0], // 1 orange
[ 0, 158, 115], // 2 bluish green
[204, 121, 167], // 3 reddish purple
];
const MARGIN = { top: 56, right: 24, bottom: 64, left: 64 };
// ----- the synthetic dataset --------------------------------------------------
// Forty (x, y) points drawn around the line y = 0.6 * x + 4 with normal noise.
// Each row also carries a category (0..3) and a weight (3..18) used by the
// color / size encodings. Numbers are hand-chosen rather than random()-ed so
// the sketch is deterministic across reloads -- a chart should look the same
// every time the reader opens it.
const data = [
{ x: 12, y: 11.4, cat: 0, w: 6 }, { x: 18, y: 14.9, cat: 0, w: 9 },
{ x: 25, y: 18.7, cat: 0, w: 7 }, { x: 31, y: 22.9, cat: 0, w: 11 },
{ x: 36, y: 25.1, cat: 0, w: 5 }, { x: 42, y: 30.2, cat: 0, w: 8 },
{ x: 48, y: 32.6, cat: 0, w: 13 }, { x: 55, y: 38.4, cat: 0, w: 10 },
{ x: 14, y: 13.7, cat: 1, w: 8 }, { x: 21, y: 16.2, cat: 1, w: 12 },
{ x: 28, y: 21.5, cat: 1, w: 6 }, { x: 34, y: 23.8, cat: 1, w: 14 },
{ x: 40, y: 27.4, cat: 1, w: 9 }, { x: 46, y: 31.2, cat: 1, w: 11 },
{ x: 52, y: 34.0, cat: 1, w: 17 }, { x: 60, y: 39.6, cat: 1, w: 13 },
{ x: 16, y: 12.0, cat: 2, w: 10 }, { x: 22, y: 17.8, cat: 2, w: 4 },
{ x: 29, y: 19.6, cat: 2, w: 12 }, { x: 35, y: 24.4, cat: 2, w: 7 },
{ x: 41, y: 28.0, cat: 2, w: 15 }, { x: 47, y: 30.8, cat: 2, w: 9 },
{ x: 53, y: 36.1, cat: 2, w: 6 }, { x: 59, y: 38.2, cat: 2, w: 12 },
{ x: 11, y: 10.2, cat: 3, w: 5 }, { x: 17, y: 14.5, cat: 3, w: 16 },
{ x: 24, y: 17.0, cat: 3, w: 8 }, { x: 30, y: 21.8, cat: 3, w: 14 },
{ x: 38, y: 26.7, cat: 3, w: 11 }, { x: 44, y: 30.6, cat: 3, w: 6 },
{ x: 50, y: 33.3, cat: 3, w: 18 }, { x: 56, y: 37.1, cat: 3, w: 9 },
{ x: 19, y: 16.0, cat: 0, w: 7 }, { x: 27, y: 19.1, cat: 1, w: 10 },
{ x: 33, y: 22.4, cat: 2, w: 13 }, { x: 39, y: 25.8, cat: 3, w: 5 },
{ x: 45, y: 29.4, cat: 0, w: 11 }, { x: 51, y: 33.7, cat: 1, w: 8 },
{ x: 57, y: 36.9, cat: 2, w: 16 }, { x: 62, y: 40.7, cat: 3, w: 10 },
];
// Encoding toggles -- read once per frame inside draw().
let trendOn = true; // T least-squares regression line + r
let colorOn = false; // C color the dots by category
let sizeOn = false; // S scale dot size by weight
// =============================================================================
// p5 lifecycle
// =============================================================================
function setup() {
createCanvas(windowWidth, windowHeight);
textAlign(LEFT, TOP);
textFont("Helvetica");
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
// Keyboard control -- avoids HTML controls cluttering the chart area.
// t / T -> toggle trend line
// c / C -> toggle category colors
// s / S -> toggle size encoding
function keyPressed() {
if (key === "t" || key === "T") trendOn = !trendOn;
if (key === "c" || key === "C") colorOn = !colorOn;
if (key === "s" || key === "S") sizeOn = !sizeOn;
}
// =============================================================================
// draw -- deterministic render: read state, lay out, draw frame, draw glyphs
// =============================================================================
function draw() {
background(BG);
// --- chart frame geometry (margins drive the inset) -----------------------
const x0 = MARGIN.left;
const y0 = MARGIN.top;
const w = width - MARGIN.left - MARGIN.right;
const h = height - MARGIN.top - MARGIN.bottom;
// --- compute domain extents and pad them so the cloud breathes -----------
const xMin = 0;
const xMax = nextNice(maxOf(data, "x") * 1.05);
const yMin = 0;
const yMax = nextNice(maxOf(data, "y") * 1.10);
// --- scale closures (the formal core of Pattern A composition) ----------
// xScale maps a data x -> pixel x ; yScale maps a data y -> pixel y.
const xScale = function (vx) { return x0 + ((vx - xMin) / (xMax - xMin)) * w; };
const yScale = function (vy) { return y0 + h - ((vy - yMin) / (yMax - yMin)) * h; };
// --- chart frame underneath the cloud -----------------------------------
drawFrame(x0, y0, w, h, xMin, xMax, yMin, yMax);
// --- regression model (computed every frame so toggles re-fit cleanly) ---
const fit = leastSquaresFit(data);
// --- trend line (drawn first so dots sit on top) -------------------------
if (trendOn) drawTrendLine(xScale, yScale, fit, xMin, xMax);
// --- find the dot closest to the cursor in screen space ------------------
let hovered = -1;
let bestDist = 14; // pixel radius for a "hit"
for (let i = 0; i < data.length; i++) {
const dx = mouseX - xScale(data[i].x);
const dy = mouseY - yScale(data[i].y);
const d = Math.sqrt(dx * dx + dy * dy);
if (d < bestDist) { bestDist = d; hovered = i; }
}
// --- the headline glyph: one dot per observation -------------------------
drawDots(xScale, yScale, hovered);
// --- tooltip + HUD overlays (always last so they sit on top) ------------
if (hovered >= 0) drawTooltip(mouseX, mouseY, data[hovered]);
drawHud(fit);
}
// =============================================================================
// Glyphs (the dictionary entries this microsim composes)
// =============================================================================
// drawDots : the canonical glyphDot primitive. Each row becomes one circle
// at (xScale(d.x), yScale(d.y)). Color and radius vary with the encoding
// toggles. The hovered dot always uses DOT_HI so the reader sees the link
// between the dot and the tooltip.
function drawDots(xScale, yScale, hovered) {
noStroke();
for (let i = 0; i < data.length; i++) {
const d = data[i];
const cx = xScale(d.x);
const cy = yScale(d.y);
// size : default 6 px diameter ; 4..18 px when sizeOn maps weight to area
let r = 6;
if (sizeOn) r = map(d.w, 3, 18, 4, 18);
if (i === hovered) {
// hovered dot is always painted in the contrast color, slightly larger
fill(DOT_HI[0], DOT_HI[1], DOT_HI[2]);
circle(cx, cy, r + 4);
} else if (colorOn) {
const c = CAT_C[d.cat % CAT_C.length];
fill(c[0], c[1], c[2], 220);
circle(cx, cy, r);
} else {
// mono encoding -- the default "show the cloud" view
fill(DOT_C[0], DOT_C[1], DOT_C[2], 200);
circle(cx, cy, r);
}
}
}
// drawTrendLine : render y_hat = m*x + b clipped to the chart frame.
function drawTrendLine(xScale, yScale, fit, xMin, xMax) {
if (!isFinite(fit.m) || !isFinite(fit.b)) return;
const x1 = xMin;
const x2 = xMax;
const y1 = fit.m * x1 + fit.b;
const y2 = fit.m * x2 + fit.b;
noFill();
stroke(TREND_C[0], TREND_C[1], TREND_C[2], 220);
strokeWeight(2);
line(xScale(x1), yScale(y1), xScale(x2), yScale(y2));
}
// =============================================================================
// Pure helpers (small, reusable, no side effects on stroke/fill state)
// =============================================================================
// maxOf : maximum of one numeric field across the dataset.
function maxOf(arr, key) {
let m = -Infinity;
for (let i = 0; i < arr.length; i++) {
if (arr[i][key] > m) m = arr[i][key];
}
return m;
}
// nextNice : round a value up to the next "nice" axis cap (5 / 10 / 25 / 50 / 100 ...).
function nextNice(v) {
if (v <= 0) return 10;
const exp10 = Math.pow(10, Math.floor(Math.log10(v)));
const norm = v / exp10;
let nice;
if (norm <= 1.0) nice = 1.0;
else if (norm <= 2.0) nice = 2.0;
else if (norm <= 2.5) nice = 2.5;
else if (norm <= 5.0) nice = 5.0;
else nice = 10.0;
return nice * exp10;
}
// leastSquaresFit : ordinary least-squares for y = m*x + b plus the Pearson r.
// Returns NaN slope/intercept when the dataset has zero x-variance, which
// the line-drawing step checks before rendering.
function leastSquaresFit(arr) {
const n = arr.length;
let sx = 0, sy = 0;
for (let i = 0; i < n; i++) { sx += arr[i].x; sy += arr[i].y; }
const mx = sx / n;
const my = sy / n;
let num = 0, denX = 0, denY = 0;
for (let i = 0; i < n; i++) {
const dx = arr[i].x - mx;
const dy = arr[i].y - my;
num += dx * dy;
denX += dx * dx;
denY += dy * dy;
}
const m = denX === 0 ? NaN : num / denX;
const b = my - m * mx;
const r = (denX === 0 || denY === 0) ? NaN : num / Math.sqrt(denX * denY);
return { m: m, b: b, r: r, mx: mx, my: my, n: n };
}
// =============================================================================
// Chart frame -- canonical Visualization frame: axes, gridlines, tick labels,
// axis titles, chart title. Becomes chart_frame.js once extracted.
// =============================================================================
function drawFrame(x, y, w, h, xMin, xMax, yMin, yMax) {
// gridlines (light, behind everything else)
stroke(GRID[0], GRID[1], GRID[2]);
strokeWeight(1);
// five horizontal gridlines
for (let t = 0; t <= 5; t++) {
const yy = y + h - (t / 5) * h;
line(x, yy, x + w, yy);
}
// five vertical gridlines
for (let t = 0; t <= 5; t++) {
const xx = x + (t / 5) * w;
line(xx, y, xx, y + h);
}
// axes -- the L-shape that bounds the plot
stroke(AXIS[0], AXIS[1], AXIS[2]);
strokeWeight(1.5);
line(x, y, x, y + h); // left vertical axis
line(x, y + h, x + w, y + h); // bottom horizontal axis
// y tick labels
noStroke();
fill(AXIS[0], AXIS[1], AXIS[2]);
textAlign(RIGHT, CENTER);
textSize(10);
for (let t = 0; t <= 5; t++) {
const yy = y + h - (t / 5) * h;
const yv = yMin + (t / 5) * (yMax - yMin);
text(nf(yv, 1, 0), x - 6, yy);
}
// x tick labels
textAlign(CENTER, TOP);
for (let t = 0; t <= 5; t++) {
const xx = x + (t / 5) * w;
const xv = xMin + (t / 5) * (xMax - xMin);
text(nf(xv, 1, 0), xx, y + h + 6);
}
// y-axis title (rotated)
push();
translate(x - 44, y + h / 2);
rotate(-HALF_PI);
fill(AXIS[0], AXIS[1], AXIS[2]);
textAlign(CENTER, CENTER);
textSize(12);
text("y", 0, 0);
pop();
// x-axis title
fill(AXIS[0], AXIS[1], AXIS[2]);
textAlign(CENTER, TOP);
textSize(12);
text("x", x + w / 2, y + h + 28);
// chart title -- changes with the encoding state
let modeBits = [];
if (trendOn) modeBits.push("trend");
if (colorOn) modeBits.push("color");
if (sizeOn) modeBits.push("size");
const modeLabel = modeBits.length === 0 ? "raw cloud" : modeBits.join(" + ");
fill(INK[0], INK[1], INK[2]);
textAlign(LEFT, TOP);
textSize(14);
text("Scatter plot -- " + modeLabel, x, y - 22);
// restore the global text state -- helpers must not leak align
textAlign(LEFT, TOP);
}
// =============================================================================
// Tooltip + HUD
// =============================================================================
function drawTooltip(mx, my, d) {
const tip = "x " + nf(d.x, 1, 1) + " y " + nf(d.y, 1, 1) +
" cat " + d.cat + " w " + d.w;
textSize(12);
textAlign(LEFT, TOP);
const tw = textWidth(tip) + 14;
const th = 22;
// clamp so the tooltip never spills past the right edge or bottom
let tx = mx + 12;
let ty = my + 12;
if (tx + tw > width - 4) tx = mx - tw - 12;
if (ty + th > height - 4) ty = my - th - 12;
noStroke();
fill(0, 200);
rect(tx, ty, tw, th, 4);
fill(255);
text(tip, tx + 7, ty + 5);
// restore default
textAlign(LEFT, TOP);
}
function drawHud(fit) {
// --- top-left : title bar with the article slug + Wikitube URL ----------
noStroke();
fill(0, 180);
rect(8, 8, 360, 44, 4);
fill(255);
textSize(13);
textAlign(LEFT, TOP);
text(ARTICLE, 16, 13);
textSize(11);
text("en.wikitube.io/wiki/" + ARTICLE, 16, 32);
// --- top-right : control hints -----------------------------------------
const hint = "T trend . C color . S size";
textSize(11);
textAlign(RIGHT, TOP);
const hintW = textWidth(hint) + 16;
fill(0, 180);
rect(width - 8 - hintW, 8, hintW, 22, 4);
fill(255);
text(hint, width - 16, 13);
// --- bottom-left : readouts (data summary) ----------------------------
const rTxt = isFinite(fit.r) ? nf(fit.r, 1, 3) : "n/a";
const readout =
"n " + fit.n +
" x_mean " + nf(fit.mx, 1, 1) +
" y_mean " + nf(fit.my, 1, 1) +
" r " + rTxt;
textSize(11);
textAlign(LEFT, BOTTOM);
const rw = textWidth(readout) + 16;
fill(0, 180);
rect(8, height - 30, rw, 22, 4);
fill(255);
text(readout, 16, height - 14);
// --- bottom-right : equation / model definition -----------------------
const eq = isFinite(fit.m)
? "y_hat = " + nf(fit.m, 1, 3) + " * x + " + nf(fit.b, 1, 2)
: "y_hat = m * x + b";
textSize(11);
textAlign(RIGHT, BOTTOM);
const eqW = textWidth(eq) + 16;
fill(0, 180);
rect(width - 8 - eqW, height - 30, eqW, 22, 4);
fill(255);
text(eq, width - 16, height - 14);
// restore baseline state
textAlign(LEFT, TOP);
}
```
## Links (Wikipedia order)
<!-- injected from _registry/childlinks/Scatter_plot.json (2026-07-30T02:09:12Z) -->
`Accelerated_failure_time_model` · `Actuarial_science` · `Akaike_information_criterion` · `American_Society_for_Quality` · `Analysis_of_covariance` · `Analysis_of_variance` · `Anderson–Darling_test` · `Anscombe_transform` · `Arithmetic_mean` · `Arithmetic–geometric_mean` · `Asymptotic_theory_(statistics)` · [[Autocorrelation]] · `Autoregressive_conditional_heteroskedasticity` · `Autoregressive_model` · `Average_absolute_deviation` · [[Bar_chart]] · `Bayes_estimator` · `Bayes_factor` · `Bayesian_inference` · `Bayesian_information_criterion` · `Bayesian_linear_regression` · `Bayesian_probability` · `Bias_of_an_estimator` · `Binomial_regression` · [[Bioinformatics]] · `Biostatistics` · `Biplot` · `Bivariate_data` · `Blocking_(statistics)` · `Bootstrapping_(statistics)` · [[Box_plot]] · `Box–Jenkins_method` · `Breusch–Godfrey_test` · `Bubble_chart` · `Canonical_correlation` · [[Cartesian_coordinate_system]] · `Cartography` · `Categorical_variable` · `Causality` · `Census` · `Central_limit_theorem` · `Check_sheet` · `Chemometrics` · `Chi-squared_test` · `Clinical_study_design` · `Clinical_trial` · `Cluster_analysis` · `Cluster_sampling` · `Cochran–Mantel–Haenszel_statistics` · `Coefficient_of_determination` · `Coefficient_of_variation` · `Cohen's_kappa` · `Cohort_study` · `Cointegration` · `Completeness_(statistics)` · `Confidence_interval` · `Confounding` · `Contingency_table` · `Contraharmonic_mean` · `Control_chart` · `Correlation` · `Correlogram` · `Count_data` · `Credible_interval` · `Crime_statistics` · `Cross-correlation` · `Cross-sectional_study` · `Cross-validation_(statistics)` · `Cubic_mean` · `Curve_fitting` · `Data_and_information_visualization` · `Data_collection` · `Data_preprocessing` · `Data_transformation_(statistics)` · `Decomposition_of_time_series` · `Degrees_of_freedom_(statistics)` · `Demographic_statistics` · `Density_estimation` · `Descriptive_statistics` · `Design_of_experiments` · `Dickey–Fuller_test` · `Dimensionality_reduction` · `Divergence_(statistics)` · `Dot_plot_(statistics)` · `Durbin–Watson_statistic` · `Econometrics` · `Effect_size` · `Efficiency_(statistics)` · `Elliptical_distribution` · `Empirical_distribution_function` · `Engineering_statistics` · `Environmental_statistics` · `Epidemiology` · `Errors_and_residuals` · `Estimating_equations` · `Experiment` · `Exponential_family` · `Exponential_smoothing` · `F-test` · `Factor_analysis` · `Factorial_experiment` · `Failure_rate` · `Fan_chart_(statistics)` · `Feature_scaling` · `First-hitting-time_model` · `Fisher_transformation` · `Forest_plot` · [[Fourier_analysis]] · [[Frequency_domain]] · `Frequentist_inference` · `Friedman_test` · `G-test` · `General_linear_model` · `Generalized_linear_model` · `Generalized_mean` · `Geographic_information_system` · `Geometric_mean` · `Geostatistics` · `Goodness_of_fit` · `Granger_causality` · `Graphical_model` · `Grouped_data` · `Harmonic_mean` · `Heinz_mean` · `Heronian_mean` · [[Histogram]] · `Hodges–Lehmann_estimator` · `Homoscedasticity_and_heteroscedasticity` · `Index_of_dispersion` · `Interaction_(statistics)` · `Interquartile_range` · `Interval_estimation` · `Ishikawa_diagram` · `Isotonic_regression` · `Jackknife_resampling` · `Jarque–Bera_test` · `Johansen_test` · `John_Herschel` · `Jonckheere's_trend_test` · `Jurimetrics` · `Kaplan–Meier_estimator` · `Karl_Pearson` · `Kendall_rank_correlation_coefficient` · `Kolmogorov–Smirnov_test` · `Kriging` · `Kruskal–Wallis_test` · `Kurtosis` · `L-moment` · [[Least-squares_spectral_analysis]] · `Lehmann–Scheffé_theorem` · `Lehmer_mean` · `Likelihood-ratio_test` · `Likelihood_function` · `Lilliefors_test` · [[Line_chart]] · `Linear_discriminant_analysis` · `Linear_regression` · `List_of_fields_of_application_of_statistics` · `List_of_mathematical_art_software` · `List_of_statistical_tests` · `List_of_statistics_articles` · `Ljung–Box_test` · `Local_regression` · `Location_parameter` · `Location–scale_family` · `Logistic_regression` · `Loss_function` · `Lp_space` · `M-estimator` · `Mann–Whitney_U_test` · `Mathematical_diagram` · `Maximum_a_posteriori_estimation` · `McNemar's_test` · `Median` · `Medical_statistics` · `Method_of_moments_(statistics)` · `Methods_engineering` · `Minimum-variance_unbiased_estimator` · `Missing_data` · `Mixed_model` · `Mixture_model` · `Mode_(statistics)` · `Model_selection` · `Moment_(mathematics)` · `Monotone_likelihood_ratio` · `Mosaic_plot` · `Multivariate_analysis_of_variance` · `Multivariate_normal_distribution` · `Multivariate_statistics` · `National_accounts` · `Natural_experiment` · `Nelson–Aalen_estimator` · `Nonlinear_regression` · `Nonparametric_regression` · `Nonparametric_statistics` · `Normalization_(statistics)` · `Observational_study` · `Official_statistics` · `One-_and_two-tailed_tests` · `Opinion_poll` · `Optimal_decision` · `Order_statistic` · `Ordinary_least_squares` · `Outlier` · `Outline_of_statistics` · `Parameter` · `Parametric_statistics` · `Pareto_chart` · `Partial_autocorrelation_function` · `Partial_correlation` · `Partition_of_sums_of_squares` · `Pearson_correlation_coefficient` · `Percentile` · `Permutation_test` · [[Phase_space]] · `Pie_chart` · `Pivotal_quantity` · `Plot_(graphics)` · `Point_estimation` · `Poisson_regression` · `Posterior_probability` · `Power_(statistics)` · `Power_transform` · `Prediction_interval` · `Principal_component_analysis` · `Prior_probability` · `Probabilistic_design` · `Probability_distribution` · `Proportional_hazards_model` · `Psychometrics` · `Quality_(business)` · `Quality_control` · `Quasi-experiment` · `Questionnaire` · `Q–Q_plot` · `Radar_chart` · `Random_assignment` · `Randomized_controlled_trial` · `Randomized_experiment` · `Range_(statistics)` · `Rank_correlation` · `Ranking_(statistics)` · `Rao–Blackwell_theorem` · `Regression_analysis` · `Regression_validation` · [[Reliability_engineering]] · `Replication_(statistics)` · `Resampling_(statistics)` · `Robust_regression` · `Robust_statistics` · `Run_chart` · `Sample_size_determination` · `Sampling_(statistics)` · `Sampling_distribution` · `Scale_parameter` · `Scientific_control` · `Score_test` · `Seasonal_adjustment` · `Semiparametric_regression` · `Seven_basic_tools_of_quality` · `Shape_parameter` · `Shapiro–Wilk_test` · `Sign_test` · `Simple_linear_regression` · `Simultaneous_equations_model` · `Skewness` · `Social_statistics` · `Spatial_analysis` · `Spearman's_rank_correlation_coefficient` · `Spectral_density_estimation` · `Standard_deviation` · `Standard_error` · `Standard_score` · `Stationary_process` · `Statistic` · `Statistical_classification` · `Statistical_dispersion` · `Statistical_distance` · `Statistical_graphics` · `Statistical_hypothesis_test` · `Statistical_inference` · `Statistical_model` · `Statistical_parameter` · `Statistical_population` · `Statistical_process_control` · `Statistical_theory` · `Statistics` · `Stem-and-leaf_display` · `Stochastic_approximation` · `Stratified_sampling` · `Structural_break` · `Structural_equation_modeling` · `Student's_t-test` · `Sufficient_statistic` · `Survey_methodology` · `Survival_analysis` · `Survival_function` · [[System_identification]] · [[Time_domain]] · [[Time_series]] · `Tolerance_interval` · `Truncation_(statistics)` · `U-statistic` · `Uniformly_most_powerful_test` · `V-statistic` · `Van_der_Waerden_test` · `Variable_(mathematics)` · `Variance` · `Variance-stabilizing_transformation` · `Vector_autoregression` · `Violin_plot` · `Wald_test` · `Wavelet` · [[Wayback_Machine]] · `Whittle_likelihood` · `Wilcoxon_signed-rank_test` · `William_S._Cleveland` · `Winsorizing` · `Wyoming` · `Yellowstone_National_Park` · `Z-test`
## From the Real GENERATIVE library

*Scatter plot — placed from the Real G.E.N.E.R.A.T.I.V.E. course library (Visualization room). Source: Wikimedia Commons (via Wikipedia article media). [Details & license](https://commons.wikimedia.org/wiki/File:Scatter_diagram_for_quality_characteristic_XXX.svg).*
> A scatter plot, also called a scatterplot, scatter graph, scatter chart, scattergram, or scatter diagram,[2] is a type of plot or mathematical diagram using Cartesian coordinates to display values for typically two variables for a set of data. If the points are coded (color/shape/size), one additional variable can be displayed. ([Wikipedia](https://en.wikipedia.org/wiki/Scatter_plot))
<!-- REAL-GENERATIVE-MEDIA:END -->
<!-- LOCAL-MEDIA-PASS:START -->
## From the vault media library
!Scatter plot thumb.png
*Scatter Plot — from the vault's own media holdings, placed 2026-07-09. MTN / Wikitube.io original · CC BY-SA 4.0.*
<!-- LOCAL-MEDIA-PASS:END -->
> **Room:** Visualization · **Status:** ✅ shipped
## Overview
A **scatter plot** is the canonical chart for showing the relationship between two quantitative variables. Each observation becomes a single dot positioned at its `(x, y)` coordinate, and the eye reads correlation, clustering, and outliers directly off the cloud — no aggregation, no binning, no smoothing required. The form was used by the Anglo-Irish astronomer John Herschel in the 1830s, popularised by Karl Pearson alongside the correlation coefficient he co-developed with Galton, and has been the default tool of exploratory data analysis ever since John Tukey gave that practice its name.
The visual contract is unusually clean. The two axes are independent and equal in status — neither is a category — and the single mark per row maps observations to pixels in the most direct way any chart type allows. A scatter plot is honest about what the data is: a cloud, not a curve, not a bar. Encoding extra dimensions through marker size (the bubble chart degenerate case), color (categorical or continuous), and shape is straightforward; the danger is overplotting once the dataset grows past a few hundred points.
This microsim ships the room's reference scatter [[Implementation|implementation]]: a `drawChartFrame` axis [[System|system]], a `glyphDot` primitive with size and color encodings, hover-driven tooltips, and an opt-in least-squares trend line that prints its slope, intercept, and Pearson `r` next to the equation footer.
## See also
- Room hub: Visualization
- p5.js Editor conventions: P5 JS EDITOR
- Wiki root: MAIN
---
*Scaffolded by `generative-microsim` from row 0 of the Visualization sheet on 2026-04-30T14:12:36Z.*
<!-- REAL-GENERATIVE-MEDIA:START -->
<!-- CRAFT-LINK:START g12 -->
*Built to the [[WT!P5_js_Microsim_Master_Class|p5.js Master Class]].*
<!-- CRAFT-LINK:END -->
## Wikipedia : Wikitube
**Strict pair:** [Wikipedia](https://en.wikipedia.org/wiki/Scatter_plot) : [Wikitube](https://en.wikitube.io/wiki/Scatter_plot)
## Previous hub tags
Tree parents: [[Monte_Carlo_method]] · [[Reliability_engineering]].
Legacy hubs: `GENERATIVE`.
---
*Sources: 1 legacy note. Minted wave 1, 2026-07-30 (v1.6 order).*