Histogram
Summarize one measure in deterministic numeric bins.
Chart ID: histogram. Independent import: @revolist/charts/histogram.
Live example
Section titled “Live example”Loading chart…
Reading the chart
Section titled “Reading the chart”Read the frequency or aggregate within numeric bins. Bin placement uses the selected numeric values; an independently bound Y measure can supply sums or means instead of counts.
Data requirements
Section titled “Data requirements”Use one category per row and one or more numeric series. Values are finite numbers or explicit nulls; the row mapper does not group or aggregate repeated keys.
The roles below describe the chart's data contract. Generic category/value roles resolve from the dataset; explicitly bind specialized numeric roles as shown in the complete example.
| Data role | Field count |
|---|---|
category | 1 or more |
value | 1 or more |
series | 1 or more |
Download the complete sample data and settings (JSON). See Data & Configuration for mapping, null values, updates and lifecycle rules.
Create this chart
Section titled “Create this chart”Install the package using the installation guide, give the host an explicit height, and call createHistogramChart after the host mounts. This factory fixes the chart type to histogram.
<div id="chart" style="width: 100%; height: 450px;"></div>Complete runnable TypeScript example with sample data
import { createHistogramChart } from '@revolist/charts/histogram';
const container = document.getElementById('chart')!;const chart = await createHistogramChart({ container, "dataset": { "revision": 0, "source": "client", "categories": [ { "id": "preview-category-0", "label": "12", "path": [ "12" ], "labels": [ "12" ], "depth": 1, "kind": "leaf" }, { "id": "preview-category-1", "label": "18", "path": [ "18" ], "labels": [ "18" ], "depth": 1, "kind": "leaf" }, { "id": "preview-category-2", "label": "23", "path": [ "23" ], "labels": [ "23" ], "depth": 1, "kind": "leaf" }, { "id": "preview-category-3", "label": "27", "path": [ "27" ], "labels": [ "27" ], "depth": 1, "kind": "leaf" }, { "id": "preview-category-4", "label": "31", "path": [ "31" ], "labels": [ "31" ], "depth": 1, "kind": "leaf" }, { "id": "preview-category-5", "label": "35", "path": [ "35" ], "labels": [ "35" ], "depth": 1, "kind": "leaf" }, { "id": "preview-category-6", "label": "42", "path": [ "42" ], "labels": [ "42" ], "depth": 1, "kind": "leaf" }, { "id": "preview-category-7", "label": "48", "path": [ "48" ], "labels": [ "48" ], "depth": 1, "kind": "leaf" } ], "series": [ { "id": "preview-series-0", "label": "Value", "columnPath": [ "Value" ], "labels": [ "Value" ], "kind": "leaf", "prop": "preview-0" } ], "values": [ [ 12 ], [ 18 ], [ 23 ], [ 27 ], [ 31 ], [ 35 ], [ 42 ], [ 48 ] ], "analyticalFrame": { "derived": { "distributions": [ { "kind": "samples", "categoryId": "preview-category-0", "seriesId": "preview-series-0", "samples": [ 8, 12, 14, 18, 19, 23, 27, 31, 48 ] }, { "kind": "samples", "categoryId": "preview-category-1", "seriesId": "preview-series-0", "samples": [ 10, 14, 16, 20, 21, 25, 29, 33, 50 ] }, { "kind": "samples", "categoryId": "preview-category-2", "seriesId": "preview-series-0", "samples": [ 12, 16, 18, 22, 23, 27, 31, 35, 52 ] }, { "kind": "samples", "categoryId": "preview-category-3", "seriesId": "preview-series-0", "samples": [ 14, 18, 20, 24, 25, 29, 33, 37, 54 ] }, { "kind": "samples", "categoryId": "preview-category-4", "seriesId": "preview-series-0", "samples": [ 16, 20, 22, 26, 27, 31, 35, 39, 56 ] }, { "kind": "samples", "categoryId": "preview-category-5", "seriesId": "preview-series-0", "samples": [ 18, 22, 24, 28, 29, 33, 37, 41, 58 ] }, { "kind": "samples", "categoryId": "preview-category-6", "seriesId": "preview-series-0", "samples": [ 20, 24, 26, 30, 31, 35, 39, 43, 60 ] }, { "kind": "samples", "categoryId": "preview-category-7", "seriesId": "preview-series-0", "samples": [ 22, 26, 28, 32, 33, 37, 41, 45, 62 ] } ] }, "fields": [ { "id": "pivot:category", "label": "pivot:category", "role": "dimension", "semanticType": "category" }, { "id": "pivot:series", "label": "pivot:series", "role": "dimension", "semanticType": "category" }, { "id": "preview-series-0", "label": "Value", "role": "measure", "semanticType": "number", "sourceField": "preview-0" } ], "observations": [ { "id": "[\"preview-category-0\",\"preview-series-0\"]", "dimensions": { "pivot:category": { "value": "12", "label": "12", "path": [ "12" ], "labels": [ "12" ] }, "pivot:series": { "value": "Value", "label": "Value", "path": [ "Value" ], "labels": [ "Value" ] } }, "measures": { "preview-series-0": 12 } }, { "id": "[\"preview-category-1\",\"preview-series-0\"]", "dimensions": { "pivot:category": { "value": "18", "label": "18", "path": [ "18" ], "labels": [ "18" ] }, "pivot:series": { "value": "Value", "label": "Value", "path": [ "Value" ], "labels": [ "Value" ] } }, "measures": { "preview-series-0": 18 } }, { "id": "[\"preview-category-2\",\"preview-series-0\"]", "dimensions": { "pivot:category": { "value": "23", "label": "23", "path": [ "23" ], "labels": [ "23" ] }, "pivot:series": { "value": "Value", "label": "Value", "path": [ "Value" ], "labels": [ "Value" ] } }, "measures": { "preview-series-0": 23 } }, { "id": "[\"preview-category-3\",\"preview-series-0\"]", "dimensions": { "pivot:category": { "value": "27", "label": "27", "path": [ "27" ], "labels": [ "27" ] }, "pivot:series": { "value": "Value", "label": "Value", "path": [ "Value" ], "labels": [ "Value" ] } }, "measures": { "preview-series-0": 27 } }, { "id": "[\"preview-category-4\",\"preview-series-0\"]", "dimensions": { "pivot:category": { "value": "31", "label": "31", "path": [ "31" ], "labels": [ "31" ] }, "pivot:series": { "value": "Value", "label": "Value", "path": [ "Value" ], "labels": [ "Value" ] } }, "measures": { "preview-series-0": 31 } }, { "id": "[\"preview-category-5\",\"preview-series-0\"]", "dimensions": { "pivot:category": { "value": "35", "label": "35", "path": [ "35" ], "labels": [ "35" ] }, "pivot:series": { "value": "Value", "label": "Value", "path": [ "Value" ], "labels": [ "Value" ] } }, "measures": { "preview-series-0": 35 } }, { "id": "[\"preview-category-6\",\"preview-series-0\"]", "dimensions": { "pivot:category": { "value": "42", "label": "42", "path": [ "42" ], "labels": [ "42" ] }, "pivot:series": { "value": "Value", "label": "Value", "path": [ "Value" ], "labels": [ "Value" ] } }, "measures": { "preview-series-0": 42 } }, { "id": "[\"preview-category-7\",\"preview-series-0\"]", "dimensions": { "pivot:category": { "value": "48", "label": "48", "path": [ "48" ], "labels": [ "48" ] }, "pivot:series": { "value": "Value", "label": "Value", "path": [ "Value" ], "labels": [ "Value" ] } }, "measures": { "preview-series-0": 48 } } ], "matrixCells": [ { "categoryId": "preview-category-0", "seriesId": "preview-series-0", "observationId": "[\"preview-category-0\",\"preview-series-0\"]", "measureFieldId": "preview-series-0" }, { "categoryId": "preview-category-1", "seriesId": "preview-series-0", "observationId": "[\"preview-category-1\",\"preview-series-0\"]", "measureFieldId": "preview-series-0" }, { "categoryId": "preview-category-2", "seriesId": "preview-series-0", "observationId": "[\"preview-category-2\",\"preview-series-0\"]", "measureFieldId": "preview-series-0" }, { "categoryId": "preview-category-3", "seriesId": "preview-series-0", "observationId": "[\"preview-category-3\",\"preview-series-0\"]", "measureFieldId": "preview-series-0" }, { "categoryId": "preview-category-4", "seriesId": "preview-series-0", "observationId": "[\"preview-category-4\",\"preview-series-0\"]", "measureFieldId": "preview-series-0" }, { "categoryId": "preview-category-5", "seriesId": "preview-series-0", "observationId": "[\"preview-category-5\",\"preview-series-0\"]", "measureFieldId": "preview-series-0" }, { "categoryId": "preview-category-6", "seriesId": "preview-series-0", "observationId": "[\"preview-category-6\",\"preview-series-0\"]", "measureFieldId": "preview-series-0" }, { "categoryId": "preview-category-7", "seriesId": "preview-series-0", "observationId": "[\"preview-category-7\",\"preview-series-0\"]", "measureFieldId": "preview-series-0" } ] } }, "bindings": {}, "presentation": { "dataLabels": false }});
// When the host unmounts:// chart.destroy();Await updates before reading a snapshot or exporting. Call chart.destroy() when the host unmounts. See the live catalog to interact with this type.
Supported options
Section titled “Supported options”Set these fields in chartOptions. The option schema validates supported keys, ranges and choices; updating chartOptions replaces that authored object.
| Option | Default | Accepted values |
|---|---|---|
showGridLines | true | true or false |
markOpacity | 1 | 0.2 to 1; step 0.05 |
binCount | 0 | 0 to 256; step 1 |
histogramBinBoundaries | [] | 2 to 257 increasing finite edges, or [] for automatic binning |
histogramAggregation | count | count, sum, mean |
histogramArea | false | true or false |
Configure primary, secondary or named aggregate Y axes and primary or named numeric bin-boundary X axes, including scales, bounds, reversal, formatting, ticks and measured placement. Explicit sample bindings own independent distributions and axis assignments; X uses sample values and Y uses bin counts, sums or means. See histogram-axis options and limits and stable sample navigation.
Titles, legends, theme and labels belong to presentation or the corresponding top-level setting. Axis, color, navigation and interaction support depends on the selected chart; see Data & Configuration.
For bin sample scales and aggregate metric bounds, transforms, reversal, ticks and placement, see Histogram bin and metric axes. See Histogram sample navigation for local sample-window zoom/pan, navigator, brushes, CSV and synchronization. See Histogram shared hover and crosshair for bin-metric readouts and formatter metadata. Remote detail loading uses complete source frames, which also support precomputed equal/irregular intervals. Named sample and metric axes are supported through the collection contract below.
Related charts
Section titled “Related charts”- Strip and dot plot — Show the distribution of individual values along one axis.
Charts overview · Installation · Data & Configuration
Use chartOptions.histogramBinBoundaries to configure explicit raw-sample intervals, including irregular widths. It overrides automatic bin counts and is also available in Pivot’s Bin boundaries appearance field.
Set chartOptions.histogramArea: true for raw-width area encoding, including density axes, navigator values and typed tooltip metadata.
Inspect loaded records and complete bin statistics with histogram sample/bin data views, shared with Pivot’s Samples/Bins Data tab.
Histogram collections and axes
Section titled “Histogram collections and axes”A histogram can display several explicitly bound distributions, using the shared Charts engine in standalone Charts and Pivot. Each sample measure owns its partition and X/Y-axis assignments. Raw observations and metric/helper measures remain in the canonical dataset.
const chart = await createChart({ container, chartType: 'histogram', dataset, bindings: { x: ['duration', 'delay'], y: ['weight', 'cost'], }, chartOptions: { binCount: 12, histogramAggregation: 'sum' }, axes: { x: { scale: 'linear', unit: 's', title: 'Duration' }, xAxes: { delayAxis: { scale: 'symlog', constant: 1, reverse: true, unit: 'ms', title: 'Delay' }, }, y: { min: 0, unit: 'kg' }, yAxes: { money: { min: 0, unit: 'EUR', title: 'Cost' } }, }, seriesOverrides: { duration: { color: '#2563eb' }, delay: { xAxis: 'delayAxis', yAxis: 'money', color: '#d97706' }, }, navigation: { enabled: true, navigator: { series: 'all' }, xAxis: 'delayAxis' }, rangeSelection: { enabled: true, xAxis: 'delayAxis' },});Binding and geometry contracts
Section titled “Binding and geometry contracts”| Field | Meaning |
|---|---|
bindings.x | Ordered list of sample measure IDs. |
bindings.value | Equivalent sample-binding form. If both it and X are nonempty, their IDs/order must agree. |
bindings.y | Omit to use each sample measure as its own sum/mean metric; use one ID for a shared metric, or one distinct ID per sample for paired metrics. Count still counts sample observations. |
seriesOverrides[sampleId].xAxis | 'primary' or a configured axes.xAxes ID. Default primary. |
seriesOverrides[sampleId].yAxis | 'primary', 'secondary' or a configured axes.yAxes ID. Default primary. |
seriesOverrides[sampleId].color, .visible | Saved sample paint and visibility. Helpers do not acquire histogram marks or legend entries. |
Without explicit nonempty sample bindings, the first dataset measure remains the single legacy sample. Extra measures are not automatically added as distributions. Binding IDs must exist. Duplicate sample IDs, conflicting value/X lists and invalid metric cardinality reject before replacing the frame. The raw measure count is now governed by the normal chart limits rather than a two-measure cap.
Every member independently uses binCount, histogramBinBoundaries,
histogramAggregation and histogramArea. Automatic partitions can differ even
when members share X. Explicit raw boundaries give them a common partition.
Same-axis distributions overlay; they are not stacked, added, dodged or merged.
Use markOpacity, sample colors, visibility or separate named axes deliberately.
A logical X axis uses the union of its visible complete partition bounds, with its authored bounds taking precedence. A logical Y axis uses all visible member metrics on that axis. Overflowed sums share one finite geometry unit per Y axis; this does not add distributions together or change source values. Empty/null samples and missing metric contributors keep their existing histogram semantics. Hidden groups do not influence inferred geometry, and hiding a sample never removes its raw sample/metric fields or complete source statistics.
Primary/secondary/named metric axes and named sample axes support existing
numeric scale, domain, reversal, placement, tick, title, formatting and color
controls. Numeric X still supports linear/log/symlog/sqrt; category is the legacy
bin presentation. X comes from the bound sample, so category data/level
mappings, grouped category bands and time X are not histogram options. Logs
require positive samples/metrics under the existing rules. Unknown axes reject
atomically, including assignments on hidden members.
Area encoding divides each member’s aggregate by its raw interval width. A shared density Y axis displays a unit only when all contributing density units agree; otherwise per-bin tooltips retain each unit and the axis is numeric. Synchronization uses the full density-unit set to prevent matching a mixed axis to an unrelated raw or single-unit axis. Primary Y remains the only synchronized value axis; secondary/named Y projections use complete bins and authored bounds.
Inspection, navigation and export
Section titled “Inspection, navigation and export”Plot gestures/navigator use navigation.xAxis; a brush can independently use
rangeSelection.xAxis. viewport.xAxes[id] stores each named window. Reversal
changes projection, not source identities or increasing semantic bounds.
Navigator series can choose the first visible sample (default), 'all' or
explicit sample IDs on its selected X. Existing navigator series overrides and
colors apply to the derived metric paths; these remain noninteractive previews
of bin metrics rather than replacement source records.
Shared/crosshair readouts and peer hover use only distributions on the same
logical X axis. Each bin retains its own interval even when partitions differ.
context.aggregate now includes sampleSeriesId, valueSeriesId, xAxis and
yAxis alongside the existing raw count/sum/mean and interval fields. The
representative context.series remains the metric measure for sum/mean.
Shared tooltip formatters can read context.histogramItems, an array of
ChartHistogramTooltipItem values containing category, series, value,
displayValue, color and aggregate. Representatives may be outside the loaded
row slice, so these are not fabricated matrix-cell sharedItems. The display is
bounded to 20 aggregate peers and uses omittedSharedItemCount for additional
members. The main hovered aggregate remains available separately. Genuine
singleton activation still sends its canonical sample value; aggregate bins do
not invent click/drill records.
CSV with dataScope: 'all' remains the raw loaded matrix. Current-scope raw CSV
uses the union of rows whose sample is visible in any bound distribution’s own
window. It does not replace cells with counts, densities or overflowed aggregate
values. Complete remote statistics never fabricate unloaded CSV observations.
Models, SVG server rendering, hydration and SVG/image exports retain the normal
shared lifecycle and persisted axes/options.
Data views and Pivot controls
Section titled “Data views and Pivot controls”import { createChartHistogramDataView, createChartHistogramDataViews } from '@revolist/charts';const allDistributions = createChartHistogramDataViews(chart.model, { dataScope: 'current' });const delays = createChartHistogramDataView(chart.model, { sampleSeriesId: 'delay', dataScope: 'all',});createChartHistogramDataView keeps its first-bound-member default and adds
optional sampleSeriesId. createChartHistogramDataViews returns every bound
member in binding order and accepts dataScope only. Both validate the model,
return owned snapshots, and use each sample’s own X assignment/window.
Unknown requested samples reject. Existing samples/bins fields retain their
raw/complete-statistics distinction. Empty collections return an empty plural
array; the singular empty-data snapshot remains available.
The Pivot chart facade exports the corresponding
createPivotChartHistogramDataView / createPivotChartHistogramDataViews and
shared types. In Data, Sample series chooses the member whose raw samples
and complete bin table are inspected. The choice is transient UI state. Its UI
policy is dataView.histogramSeries; parent dataView policies still apply.
Localize the caption with localeText.histogramData.sampleSeries.
Existing Customize → Axes and scales controls edit configured primary, secondary and named axes. Per-series X/Y assignments are shown only for sample members. Chart/legend color and visibility controls target the sample, not its weight helper. Bind collection members through the model/API; this does not add a separate histogram binding-builder UI or a Pivot-specific rendering engine.
Complete remote collection summaries
Section titled “Complete remote collection summaries”The singleton primary-axis source protocol is unchanged: request histogram,
response analyticalFrame.derived.histogram. Multiple members, or a member with
a nonprimary X/Y assignment, use request histograms and response
analyticalFrame.derived.histograms. Arrays are keyed by sample ID; response
summary order does not determine plot order. Singular/plural summary metadata
are mutually exclusive.
Each ChartHistogramCollectionSourceRequest adds these fields to the existing
bin-count/boundaries/aggregation/scale/symlog-constant hints:
| Field | Contract |
|---|---|
sampleSeriesId | Requested source sample measure. |
valueSeriesId | Its shared or paired aggregation measure. |
xAxis | Identity used for the partition’s full X metadata. |
yAxis | Identity of its plotted metric axis. |
The provider returns exactly one validated ChartHistogramSummary per requested
sample, with matching sample/value IDs and applied options. Counts, sums, means,
representatives, boundaries and finite sum multipliers are global statistics,
independent of loaded rows. Use fullDomain.x for primary X and
fullDomain.xAxes[id] for named X. Each domain equals the union of complete raw
partition boundaries assigned to that axis and has the requested transform.
Named-only source domains are accepted when no primary X is used. There must be
at least one full numeric/time X domain under the shared source contract.
Histogram source assignments require explicit sample bindings when the field
identities cannot be inferred before the first load.
fullDomain.y, when supplied, still describes primary Y in the applied raw
aggregation units. Area encoding ignores that raw hint and derives global
densities from complete bins. Secondary/named-Y global metrics are likewise
inferred from their complete summaries. Authored axis bounds still win.
A missing/mismatched partition or domain rejects the response without replacing the accepted chart. Global statistics stay stable within one source revision and partition/field request; changing only the loaded window, summary order or axis identity must not alter them. A changed bin policy/transform is a new partition request. Paint/visibility changes do not reload the source. The last accepted complete frame stays visible through loading or errors. Saved models retain accepted summaries; source handles/controllers remain application-owned.
Pivot viewport providers receive the same chart.histogram /
chart.histograms hints, with cloned request ownership and exact primary/named
window echoes. Normal Pivot scope/query/revision correlation remains in force.
PivotChartHistogramCollectionSourceRequest and
PivotChartHistogramTooltipItem alias the shared public types.
Standalone histogram collections do not add stacking, independent Y navigation or generic histogram analytical overlays. To combine complete histogram bins with other Cartesian layers, use the distinct bubble and histogram combination contract. The MUI axes reference describes the upstream independent-axis model; these histogram contracts retain the framework-neutral Charts bindings and complete-source semantics.