# Bar chart ## Microsim ### Live player <div class="microsim-player"> <iframe src="https://editor.p5js.org/sciencenibber/full/z-LBlAFpt" width="100%" height="620" frameborder="0" sandbox="allow-scripts allow-same-origin"></iframe> </div> <div class="microsim-fallback"> <img src="Microsims/thumbs/Bar_chart.png" alt="Bar_chart 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/z-LBlAFpt">open sketch in the p5.js editor</a></em></p> </div> **Editor URL:** https://editor.p5js.org/sciencenibber/sketches/z-LBlAFpt **Description (100 words):** Eight monthly values rendered as labeled bars over a tick-and-grid chart frame. Hover any bar for a tooltip that follows the cursor and clamps to the canvas edge. The "sort by value" button toggles between calendar order and a descending sort, so the reader can compare the same data through two orderings without losing the encoding. The "non-zero baseline" slider deliberately violates Tufte's most famous rule — lifting the y-axis off zero exaggerates differences and lights a red warning ribbon with a live lie-factor readout. The category-colours toggle swaps the neutral hue for a Tableau-10 palette, demonstrating the data-ink tax that decorative encoding levies. ```js // ===================================================================== // Bar_chart.js · GENERATIVE / Visualization room (Pattern A composition) // // Canonical bar-chart microsim for the Wikitube wiki. Renders a small // monthly dataset as vertical bars over a labelled chart frame, with a // hover tooltip, a sort-by-value toggle, and an opt-in non-zero baseline // slider that lights up a warning ribbon when engaged (the canonical // Tufte "lie factor" violation, made visible). // // This sketch is the reference implementation referenced by P5_JS_EDITOR // section 11 — every other Pattern A chart in the room (Line_chart, // Scatter_plot, Histogram, ...) forks from it by swapping the inner // glyph loop while keeping the chart-frame, scale closures, tooltip, and // HUD untouched. // // Parameters (controls): // sortBtn — flip between calendar order and value-sorted bars. // baselineSlider — 0 (zero baseline, honest) ... 100 (zoomed-in // baseline, dishonest). Triggers a red warning // ribbon along the top of the chart frame. // colorBtn — toggle a categorical hue per bar (decorative, // low-information) versus a single neutral hue // (high data-ink ratio). // ===================================================================== // Single source of truth — used by HUD and the en.wikitube.io URL. const ARTICLE = "Bar_chart"; // Silence the p5.js Friendly Errors System. The web editor adds extra // runtime cost per draw call when FES is on, and our HUD does not need // hand-holding for missing-arg warnings. p5.disableFriendlyErrors = true; // --------------------------------------------------------------------- // Visual constants — Visualization-room neutral palette from §11. // --------------------------------------------------------------------- const BG = 250; // near-white "ink on paper" canvas const FG = 24; // body-text grey const AXIS = [80, 90, 110]; // tick lines and axis titles const GRIDC = [200, 205, 215]; // horizontal gridlines, very pale const INK = [40, 48, 60]; // chart title and labels const BAR = [70, 130, 200]; // default bar fill (blue) const BAR_HI = [220, 110, 60]; // hovered-bar accent (orange) const WARN = [220, 60, 60]; // non-zero-baseline warning ribbon const MUTED = [140, 150, 165]; // disabled / dim text // Categorical palette used by the colorBtn toggle. Eight hues chosen // from the Tableau-10 set for maximum perceptual distance. const CAT8 = [ [ 78, 121, 167], [242, 142, 43], [225, 87, 89], [118, 183, 178], [ 89, 161, 79], [237, 201, 72], [176, 122, 161], [255, 157, 167], ]; // Outer chart margins — leave room for axis labels, legend, and HUD. const MARGIN = { top: 64, right: 24, bottom: 88, left: 72 }; // Eight months of demo data. Anyone forking this sketch will replace // `data` with their own; everything else can stay verbatim. const data = [ { label: "Jan", value: 42 }, { label: "Feb", value: 37 }, { label: "Mar", value: 55 }, { label: "Apr", value: 28 }, { label: "May", value: 71 }, { label: "Jun", value: 49 }, { label: "Jul", value: 64 }, { label: "Aug", value: 38 }, ]; // Mutable UI state. Read at the top of draw() into named locals so the // rest of the frame is a pure function of the snapshot. let sortBtn, baselineSlider, colorBtn; let sorted = false; let coloured = false; function setup() { createCanvas(windowWidth, windowHeight); textFont("system-ui"); textAlign(CENTER, CENTER); // Bottom-left control rail. Three controls stacked vertically; each // line is one row of (label, control) so the layout reads as a list. sortBtn = createButton("sort by value") .position(20, height - 80) .size(180, 24) .mousePressed(() => { sorted = !sorted; }); baselineSlider = createSlider(0, 100, 0, 1) .position(220, height - 76) .size(200); colorBtn = createButton("toggle category colours") .position(20, height - 50) .size(220, 24) .mousePressed(() => { coloured = !coloured; }); } function draw() { background(BG); // ------------------------------------------------------------------- // Snapshot all interactive state into pure-function locals. // ------------------------------------------------------------------- const view = sorted ? [...data].sort((a, b) => b.value - a.value) : data; const baselineFraction = baselineSlider.value() / 100; // 0..1 // Chart-frame rectangle in canvas coords. const x0 = MARGIN.left, y0 = MARGIN.top; const w = width - MARGIN.left - MARGIN.right; const h = height - MARGIN.top - MARGIN.bottom; // Y-axis range. yMax is rounded up to the next ten; yMin lifts off // zero in proportion to baselineFraction (so the slider literally // visualises the lie factor). const rawMax = Math.max(...view.map(d => d.value)); const yMax = Math.ceil(rawMax / 10) * 10; const yMin = baselineFraction * (yMax - 10); // Scale closures. xScale maps a bar index to the centre of its slot; // yScale maps a value (in [yMin, yMax]) to a canvas y-coord (top is // small in pixel space, big in value space, hence the inversion). const xScale = (i) => x0 + (i + 0.5) * (w / view.length); const yScale = (v) => y0 + h - ((v - yMin) / (yMax - yMin)) * h; // Draw the frame (gridlines, axes, ticks, titles) before the bars // so the bars sit on top of the gridlines, not beneath them. drawChartFrame(x0, y0, w, h, view, yMin, yMax); // Hit-test once per frame — find the bar (if any) under the cursor. // Reading mouseX/mouseY directly is simpler and faster than wiring // mouseEntered/Exited handlers per bar. const barW = (w / view.length) * 0.7; let hovered = -1; for (let i = 0; i < view.length; i++) { const cx = xScale(i); const top = yScale(view[i].value); if (mouseX > cx - barW / 2 && mouseX < cx + barW / 2 && mouseY > top && mouseY < y0 + h) { hovered = i; } } // Emit the bars. Each bar is one rect from baseline to value. Colour // depends on the colour toggle and on hover state. for (let i = 0; i < view.length; i++) { const cx = xScale(i); const top = yScale(view[i].value); const base = y0 + h; const col = (i === hovered) ? BAR_HI : (coloured ? CAT8[i % CAT8.length] : BAR); fill(...col); noStroke(); rect(cx - barW / 2, top, barW, base - top, 2); // Category label under the bar. fill(...AXIS); textSize(11); textAlign(CENTER, TOP); text(view[i].label, cx, base + 6); } // Tooltip — clamped so it never escapes the canvas right edge. if (hovered >= 0) drawTooltip(mouseX, mouseY, view[hovered]); // Warning ribbon when the baseline slider is off zero. if (baselineFraction > 0.001) drawLieRibbon(x0, y0, w); drawHud(); drawControlHints(); drawReadout(view, hovered, yMin, yMax); drawEquation(); } // ===================================================================== // Chart-frame helper. Will eventually move to chart_frame.js but lives // inline here so the reference sketch stands alone. // ===================================================================== function drawChartFrame(x, y, w, h, view, yMin, yMax) { // Horizontal gridlines (six of them, including the top and bottom). stroke(...GRIDC); strokeWeight(1); for (let t = 0; t <= 5; t++) { const yy = y + h - (t / 5) * h; line(x, yy, x + w, yy); } // Y and X axis lines. stroke(...AXIS); strokeWeight(1.5); line(x, y, x, y + h); line(x, y + h, x + w, y + h); // Y-tick labels — six values across [yMin, yMax]. noStroke(); fill(...AXIS); textAlign(RIGHT, CENTER); textSize(10); for (let t = 0; t <= 5; t++) { const yy = y + h - (t / 5) * h; const v = yMin + (t / 5) * (yMax - yMin); text(nf(v, 1, 0), x - 6, yy); } // Y-axis title — rotated 90 degrees CCW so it reads bottom-to-top. push(); translate(x - 50, y + h / 2); rotate(-HALF_PI); fill(...AXIS); textAlign(CENTER, CENTER); textSize(12); text("value", 0, 0); pop(); // X-axis title. fill(...AXIS); textAlign(CENTER, TOP); textSize(12); text("month", x + w / 2, y + h + 26); // Chart title — left-aligned, just above the frame. fill(...INK); textAlign(LEFT, TOP); textSize(14); text("Monthly value - " + (sorted ? "sorted by value" : "calendar order"), x, y - 22); textAlign(CENTER, CENTER); } // Tooltip: a dark pill that follows the cursor. Width is computed from // the text so it never trims the value. function drawTooltip(mx, my, d) { const tip = `${d.label}: ${d.value}`; textSize(12); textAlign(LEFT, TOP); const tw = textWidth(tip) + 16; const tx = constrain(mx + 12, 0, width - tw - 4); const ty = constrain(my + 12, 0, height - 28); noStroke(); fill(0, 200); rect(tx, ty, tw, 22, 4); fill(255); text(tip, tx + 8, ty + 5); textAlign(CENTER, CENTER); } // Red ribbon along the top of the chart frame, with the lie factor // printed in the corner. Lights up only when baselineFraction > 0. function drawLieRibbon(x, y, w) { noStroke(); fill(...WARN, 60); rect(x, y - 6, w, 4); fill(...WARN); textSize(11); textAlign(LEFT, BOTTOM); const lie = 1 / (1 - (baselineSlider.value() / 100) * 0.999); text("non-zero baseline - lie factor " + nf(lie, 1, 2) + "x", x, y - 8); textAlign(CENTER, CENTER); } // ===================================================================== // HUD overlay — title TL, Wikitube URL TL, control hints TR, // readouts BL, equation BR. Per Visualization §11 + Betterfire Standard. // ===================================================================== function drawHud() { // Top-left strap with article title and the canonical Wikitube URL. noStroke(); fill(0, 180); rect(8, 8, 380, 26); fill(255); textSize(13); textAlign(LEFT, TOP); text(ARTICLE + " - en.wikitube.io/wiki/" + ARTICLE, 16, 14); textAlign(CENTER, CENTER); } function drawControlHints() { // Top-right: which controls do what. textAlign(RIGHT, TOP); textSize(11); noStroke(); fill(...MUTED); text("hover bars for tooltip", width - 14, 14); text("button: sort by value", width - 14, 30); text("slider: non-zero baseline", width - 14, 46); text("button: category colours", width - 14, 62); textAlign(CENTER, CENTER); } function drawReadout(view, hovered, yMin, yMax) { // Bottom-left: live snapshot of pertinent numbers. textAlign(LEFT, BOTTOM); textSize(11); noStroke(); fill(...MUTED); const total = view.reduce((s, d) => s + d.value, 0); const mean = total / view.length; let line1 = "n " + view.length + " sum " + total + " mean " + nf(mean, 1, 1); let line2 = "y in [" + nf(yMin, 1, 1) + ", " + yMax + "]"; if (hovered >= 0) { line2 += " - hover " + view[hovered].label + " " + view[hovered].value; } text(line1, 20, height - 14); text(line2, 20, height - 28); textAlign(CENTER, CENTER); } function drawEquation() { // Bottom-right: the rendering equation, exactly as in P5_JS_EDITOR §11. textAlign(RIGHT, BOTTOM); textSize(11); noStroke(); fill(...MUTED); text("y_pixel = y0 + h - (v - yMin) / (yMax - yMin) * h", width - 14, height - 14); textAlign(CENTER, CENTER); } // Resize the canvas with the window. Controls keep their absolute // positions because they were created with createButton/createSlider — // but we re-anchor the bottom row so it follows the new height. function windowResized() { resizeCanvas(windowWidth, windowHeight); sortBtn.position(20, height - 80); baselineSlider.position(220, height - 76); colorBtn.position(20, height - 50); } ``` ## Links (Wikipedia order) <!-- injected from _registry/childlinks/Bar_chart.json (2026-07-30T02:09:12Z) --> `3D_computer_graphics` · `Accelerated_failure_time_model` · `Actuarial_science` · `Akaike_information_criterion` · `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` · `Bayes_estimator` · `Bayes_factor` · `Bayesian_inference` · `Bayesian_information_criterion` · `Bayesian_linear_regression` · `Bayesian_probability` · `Bias_of_an_estimator` · `Binomial_regression` · [[Bioinformatics]] · `Biostatistics` · `Biplot` · `Blocking_(statistics)` · `Bootstrapping_(statistics)` · [[Box_plot]] · `Box–Jenkins_method` · `Breusch–Godfrey_test` · `Canonical_correlation` · `Cartography` · `Categorical_variable` · `Census` · `Central_limit_theorem` · `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` · `Correlogram` · `Count_data` · `Credible_interval` · `Crime_statistics` · `Cross-correlation` · `Cross-sectional_study` · `Cross-validation_(statistics)` · `Cubic_mean` · `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)` · `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` · `Height` · `Heinz_mean` · `Heronian_mean` · [[Histogram]] · `Hodges–Lehmann_estimator` · `Homoscedasticity_and_heteroscedasticity` · `Index_of_dispersion` · `Interaction_(statistics)` · `Interquartile_range` · `Interval_estimation` · `Isotonic_regression` · `Jackknife_resampling` · `James_R._Beniger` · `Jarque–Bera_test` · `Johansen_test` · `Jonckheere's_trend_test` · `Jurimetrics` · `Kaplan–Meier_estimator` · `Kendall_rank_correlation_coefficient` · `Kolmogorov–Smirnov_test` · `Kriging` · `Kruskal–Wallis_test` · `Kurtosis` · `L-moment` · `LM3914` · [[Least-squares_spectral_analysis]] · `Lehmann–Scheffé_theorem` · `Lehmer_mean` · `Length` · `Likelihood-ratio_test` · `Likelihood_function` · `Lilliefors_test` · [[Line_chart]] · `Linear_discriminant_analysis` · `Linear_regression` · `List_of_fields_of_application_of_statistics` · `List_of_statistical_tests` · `List_of_statistics_articles` · `Ljung–Box_test` · `Location_parameter` · `Location–scale_family` · `Logistic_regression` · `Loss_function` · `Lp_space` · `M-estimator` · `Mann–Whitney_U_test` · `Marshall_Clagett` · `Maximum_a_posteriori_estimation` · `McNemar's_test` · `Median` · `Medical_statistics` · `Method_of_moments_(statistics)` · `Methods_engineering` · `Minimum-variance_unbiased_estimator` · `Misleading_graph` · `Missing_data` · `Mixed_model` · `Mode_(statistics)` · `Model_selection` · `Moment_(mathematics)` · `Monotone_likelihood_ratio` · `Multivariate_analysis_of_variance` · `Multivariate_normal_distribution` · `Multivariate_statistics` · `National_accounts` · `Natural_experiment` · `Nelson–Aalen_estimator` · `Nicole_Oresme` · `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` · `Parametric_statistics` · `Partial_autocorrelation_function` · `Partial_correlation` · `Partition_of_sums_of_squares` · `Pearson_correlation_coefficient` · `Percentile` · `Permutation_test` · `Pie_chart` · `Pivotal_quantity` · `Point_estimation` · `Poisson_regression` · `Posterior_probability` · `Power_(statistics)` · `Power_transform` · `Prediction_interval` · `Principal_component_analysis` · `Prior_probability` · `Probabilistic_design` · `Probability_distribution` · `Product_(mathematics)` · `Progress_bar` · `Proportional_hazards_model` · `Psychometrics` · `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` · [[Scatter_plot]] · `Scientific_control` · `Score_test` · `Seasonal_adjustment` · `Semiparametric_regression` · `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]] · `Titanic` · `Tolerance_interval` · `Truncation_(statistics)` · `U-statistic` · `Uniformly_most_powerful_test` · `V-statistic` · `Van_der_Waerden_test` · `Variance` · `Variance-stabilizing_transformation` · `Vector_autoregression` · `Violin_plot` · `Wald_test` · `Wavelet` · `Whittle_likelihood` · `Wilcoxon_signed-rank_test` · `William_Playfair` · `Winsorizing` · `Z-test` ## From the Real GENERATIVE library ![Bar chart](https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Human_losses_of_world_war_two_by_country.png/310px-Human_losses_of_world_war_two_by_country.png) *Bar chart — 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:Human_losses_of_world_war_two_by_country.png).* > A bar chart or bar graph is a chart or graph that presents categorical data with rectangular bars with heights or lengths proportional to the values that they represent. The bars can be plotted vertically or horizontally. ([Wikipedia](https://en.wikipedia.org/wiki/Bar_chart)) <!-- REAL-GENERATIVE-MEDIA:END --> <!-- LOCAL-MEDIA-PASS:START --> ## From the vault media library !Bar chart thumb.png *Bar Chart — 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 **bar chart** is the canonical statistical graphic for comparing a quantitative value across a set of categories. Each category is given an equal slice of one axis and a rectangle whose length on the perpendicular axis is proportional to its value, so the eye reads "tallest = largest" with no further translation. The form was popularised by William Playfair in the *Commercial and Political Atlas* (1786) and remains, two and a half centuries later, the default chart taught in every introductory statistics course. The visual contract is unforgiving. Bars must share a common baseline of zero, otherwise differences in length stop encoding differences in value and the chart becomes a Tufte-grade lie factor. Spacing is uniform, the order of the bars is part of the message (calendar, alphabetical, sorted by value), and any color encoding should add [[Information|information]] rather than ornament — if every bar is a different color for no reason, the reader's preattentive [[System|system]] pays a tax for nothing. This microsim ships the room's reference [[Implementation|implementation]]: a `drawChartFrame` axis system, a `glyphBar` primitive, hover-driven tooltips, a sort-by-value toggle, and an opt-in non-zero-baseline slider that lights up a warning ribbon — the canonical Tufte violation, made visible. ## 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-30T12:51:52Z.* <!-- 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/Bar_chart) : [Wikitube](https://en.wikitube.io/wiki/Bar_chart) ## 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).*