diff --git a/histogram_chart/README.md b/histogram_chart/README.md index 1e79c45..0aaf5c2 100644 --- a/histogram_chart/README.md +++ b/histogram_chart/README.md @@ -1,44 +1,56 @@ # Histogram Chart -### Goal - -In this guide, we will create a Histogram Chart that subdivides a numerical range into bins, and counts the number of data points within each segment. The resulting bar chart provides a discrete estimate of the probability density function. - -![histogram_chart](https://user-images.githubusercontent.com/27631976/198895261-367ac1e3-ceee-4f6b-8b19-f0f501034d4b.png) - -### Full code example - -```jsx -CustomChart { - fields { - field grain { - type: 'dimension' - } - field metric { - type: 'dimension' // this type can be dimenson or measure depends on the type of field that you want to create the histogram on - } - } - template: @vgl - { - "data": {"values": @{values}}, - "transform": [ - {"bin": {"maxbins": 40}, "field": @{fields.metric.name}, "as": "binned_price"} - ], - "mark": { - "type": "bar", - "tooltip": true - }, - "encoding": { - "x": {"field": "binned_price", "type": "quantitative", "bin": {"binned": true, "step": 20}}, - "x2": {"field": "binned_price_end"}, - "y": {"aggregate": "count"} - } - } - ;; -} -``` - -### Applying the chart - -![applying_histogram_custom_chart](https://user-images.githubusercontent.com/27631976/198895642-e79649d7-b790-40c0-8965-d6eb018d8be5.png) +This is an updated and backwards-compatible single-series histogram chart for Holistics, built with Vega-Lite. +It bins a numeric field and counts a dimension per bin using `mark: bar`. Axis labels are dynamically generated based on the selected fields. + +--- + +## ✅ Features + +- 📊 Single-series histogram +- 🧮 Configurable number of bins +- 🏷️ Automatic axis labeling: + - X-axis: uses the binned field name + - Y-axis: "Count of {grain field}" +- 🖋 Optional chart title override + +--- + +## 📥 Fields + +| Field | Type | Description | +| -------- | -------------------- | ------------------------------------------- | +| `grain` | Dimension | The dimension to count (e.g. Examiner Name) | +| `metric` | Dimension or Measure | The numeric field to bin (e.g. hours/day) | + +--- + +## 🧰 Options + +| Option | Type | Default | Description | +| ------------- | ------------ | ------------- | ----------------------- | +| `max_bins` | number-input | `20` | Maximum number of bins | +| `chart_title` | input | `"Histogram"` | Optional title override | + +--- + +## 🔎 Example Output + +A simple bar histogram with dynamic binning and axis labels: + +- Y-axis: `"Count of Examiner Name"` +- X-axis: `"Median Examiner hr/d binned"` + +--- + +## 📁 Files + +- `README.md` – this documentation +- `vgl.aml` – the Holistics CustomChart definition + +--- + +## 🧠 Notes + +If you want to compare **multiple series** in a histogram (e.g. by time period or event type), check out [`histogram_multi_series`](../histogram_multi_series). diff --git a/histogram_chart/histogram_chart.vgl.aml b/histogram_chart/histogram_chart.vgl.aml new file mode 100644 index 0000000..4593835 --- /dev/null +++ b/histogram_chart/histogram_chart.vgl.aml @@ -0,0 +1,71 @@ +// Histogram Chart — Single-Series +// +// Renders a bar histogram with binning on a numeric field. +// Uses the selected fields to dynamically set axis titles. +// Cleaned and compatible with the original implementation, with an optional chart title override. + +CustomChart { + fields { + field grain { + label: 'Dimension to count' + type: 'dimension' + } + field metric { + label: "Measure to bin" + type: 'dimension' // this could be either a dimension or measure + } + } + + options { + option max_bins { + label: "Max bins" + type: 'number-input' + default_value: 20 + } + option chart_title { + label: "Chart title" + type: 'input' + default_value: "Histogram" + } + } + + template: @vgl + { + "title": "@{options.chart_title.value}", + "data": { + "values": @{values} + }, + "transform": [ + { + "bin": { + "maxbins": @{options.max_bins.value} + }, + "field": @{fields.metric.name}, + "as": "@{fields.metric.name} binned" + } + ], + "mark": { + "type": "bar", + "tooltip": true + }, + "encoding": { + "x": { + "field": "@{fields.metric.name} binned", + "type": "quantitative", + "title": "@{fields.metric.name} binned" + }, + "x2": { + "field": "@{fields.metric.name} binned_end" + }, + "y": { + "aggregate": "count", + "title": "Count of @{fields.grain.name}" + }, + "tooltip": [ + { "field": "@{fields.metric.name} binned", "type": "quantitative" }, + { "aggregate": "count", "type": "quantitative", "title": "Count" } + ] + } + } + ;; +} diff --git a/histogram_multi_series/README.md b/histogram_multi_series/README.md new file mode 100644 index 0000000..75e7404 --- /dev/null +++ b/histogram_multi_series/README.md @@ -0,0 +1,67 @@ +# Histogram: Multi-Series Comparison + +This chart renders a histogram of a numeric field across multiple series, using step-interpolated **area charts**. It is ideal for comparing the **shape and distribution** of different categories or time slices. + +--- + +## ✅ Features + +- 📊 Step-area histogram using Vega-Lite +- 🔢 Configurable number of bins +- 🏷 Customizable chart title and axis labels +- 🎨 Per-series color encoding +- 🧱 Two comparison modes: + - `"Stacked"`: Percent contribution by series (stacked area) + - `"Overlay"`: Compare distributions side-by-side (overlaid areas) + +--- + +## 📥 Fields + +| Field | Type | Description | +| -------- | -------------------- | --------------------------------------------- | +| `grain` | Dimension | Entity to count (e.g. ID, Examiner Name) | +| `metric` | Dimension or Measure | Numeric field to bin (e.g. hours/day) | +| `series` | Dimension | Category to group by (e.g. Event Type, Month) | + +--- + +## 🧰 Options + +| Option | Type | Default | Description | +| ------------------- | ------------ | --------------------------- | ------------------------------------------------------- | +| `max_bins` | number-input | `20` | Maximum number of histogram bins | +| `stack_bars` | select | `"none"` | `"stacked"` or `"none"` (overlay) | +| `render_as_percent` | toggle | `false` | If enabled, stacks to 100% per bin (percent comparison) | +| `chart_title` | input | `"Histogram by Series"` | Optional title override | +| `x_axis_label` | input | `"Binned Value"` | Custom X-axis label | +| `y_axis_label` | input | `"Count"` or `"Percentage"` | Custom Y-axis label | + +--- + +## 📊 Output + +Renders a normalized area chart with step interpolation. Each series is color-coded and optionally stacked or overlaid. + +This chart is especially useful for: + +- Comparing durations across phases or time periods +- Viewing distribution shifts over categories + +## 🖼 Preview + +![Histogram Multi-Series Preview](./histogram_multi_series_chart.png) + +--- + +## 📁 Files + +- `README.md` — this file +- `vgl.aml` — the Holistics CustomChart spec + +--- + +## 🧠 Notes + +- The `"render_as_percent"` option overrides `stack_bars` and always uses `stack: "normalize"`. +- For a single-series histogram, use the [`histogram_chart`](../histogram_chart) version instead. diff --git a/histogram_multi_series/histogram_multi_series.vgl.aml b/histogram_multi_series/histogram_multi_series.vgl.aml new file mode 100644 index 0000000..ede02b7 --- /dev/null +++ b/histogram_multi_series/histogram_multi_series.vgl.aml @@ -0,0 +1,116 @@ +// Custom Histogram by Series Chart for Holistics +// +// Displays a histogram of a numeric metric (e.g. hours/day), grouped by a series (e.g. event type). +// Renders a step-area chart with stacking or overlay mode. +// Axis labels are derived from the selected fields automatically. +// +// Fields: +// - grain: Dimension to count (e.g. ID or name) +// - metric: Numeric field to bin (e.g. duration) +// - series: Categorical grouping field (e.g. event type, date) +// +// Options: +// - max_bins: Number of histogram bins +// - stack_bars: Select between stacked or grouped layout +// - chart_title: Custom title for the chart + +CustomChart { + fields { + field grain { + label: 'Dimension to count' + type: 'dimension' + } + field metric { + label: "Measure to bin" + type: 'dimension' + } + field series { + label: "Series (e.g., Event Type)" + type: 'dimension' + } + } + + options { + option max_bins { + label: "Max bins" + type: 'number-input' + default_value: 20 + } + option stack_bars { + label: "Stacking Mode" + type: 'select' + default_value: "none" + options: [ + { label: "Overlay (Not Stacked)", value: "none" }, + { label: "Stacked", value: "zero" } + ] + } + option chart_title { + label: "Chart title" + type: 'input' + default_value: "" + } + } + + template: @vgl { + "title": "@{options.chart_title.value}", + "data": { + "values": @{values} + }, + "selection": { + "seriesSelector": { + "type": "multi", + "fields": ["@{fields.series.name}"], + "bind": "legend" + } + }, + "transform": [ + { + "bin": { + "maxbins": @{options.max_bins.value} + }, + "field": @{fields.metric.name}, + "as": "@{fields.metric.name} binned" + }, + { + "filter": { + "selection": "seriesSelector" + } + } + ], + "mark": { + "type": "area", + "interpolate": "step", + "opacity": 0.4, + "tooltip": true + }, + "encoding": { + "x": { + "field": "@{fields.metric.name} binned", + "type": "quantitative", + "title": "Binned @{fields.metric.name}" + }, + "y": { + "aggregate": "count", + "title": "Count of @{fields.grain.name}", + "stack": "@{options.stack_bars.value}" + }, + "color": { + "field": @{fields.series.name}, + "type": "nominal", + "title": "@{fields.series.name}" + }, + "tooltip": [ + { "field": "@{fields.series.name}", "type": "nominal" }, + { "field": "@{fields.metric.name} binned", "type": "quantitative" }, + { "aggregate": "count", "type": "quantitative", "title": "Count" } + ] + }, + "config": { + "area": { + "line": true + } + } + } + ;; +} diff --git a/histogram_multi_series/histogram_multi_series_chart.png b/histogram_multi_series/histogram_multi_series_chart.png new file mode 100644 index 0000000..1b59224 Binary files /dev/null and b/histogram_multi_series/histogram_multi_series_chart.png differ