@bicharts/chart-mcp 0.3.5 → 0.5.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -8
- package/dist/index.mjs +57 -56
- package/package.json +5 -4
- package/skills/bic-charts/CHART-SHAPES.md +124 -0
- package/skills/bic-charts/SKILL.md +50 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bicharts/chart-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.49",
|
|
4
4
|
"description": "MCP (Model Context Protocol) stdio server for BIC AI charts: profile a dataset locally, then generate chart code that has passed the BIC backend's render gates. Works with any MCP-capable client (Claude Code, Claude Desktop, Cursor, Copilot Studio). Requires a BIC trial or paid account.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"node": ">=18"
|
|
21
21
|
},
|
|
22
22
|
"bin": {
|
|
23
|
-
"bic-chart-mcp": "
|
|
23
|
+
"bic-chart-mcp": "dist/index.mjs"
|
|
24
24
|
},
|
|
25
25
|
"// files": "dist ONLY — this package ships the built server, not its source. LICENSE.txt and README.md are included automatically by npm, but listed so an audit does not have to know that.",
|
|
26
26
|
"files": [
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"build": "node build.mjs",
|
|
37
37
|
"prepack": "node build.mjs --minify",
|
|
38
38
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
39
|
+
"verify:package": "node scripts/verify-package.mjs",
|
|
39
40
|
"prestart": "node build.mjs",
|
|
40
41
|
"start": "node dist/index.mjs"
|
|
41
42
|
},
|
|
@@ -45,8 +46,8 @@
|
|
|
45
46
|
"zod": "^3.23.0"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
|
-
"@bicharts/chart-host": "^0.5.
|
|
49
|
-
"@bicharts/shape-core": "^0.5.
|
|
49
|
+
"@bicharts/chart-host": "^0.5.49",
|
|
50
|
+
"@bicharts/shape-core": "^0.5.49",
|
|
50
51
|
"@types/node": "^20.0.0",
|
|
51
52
|
"@types/papaparse": "^5.3.14",
|
|
52
53
|
"esbuild": "^0.28.1",
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# What shape feeds which chart
|
|
2
|
+
|
|
3
|
+
**Generated from the chart catalogue - do not hand-edit.**
|
|
4
|
+
Regenerate with `python tools/gen_chart_shapes.py`; a test fails the build if this
|
|
5
|
+
file and the catalogue disagree, so it cannot quietly go stale.
|
|
6
|
+
|
|
7
|
+
Use it to AIM before you write a query: pick the chart you want, read what it needs,
|
|
8
|
+
then pull a table with that shape. `assess_data_shape` (free, local) will tell you
|
|
9
|
+
whether the pull you built actually has it.
|
|
10
|
+
|
|
11
|
+
**Read the LIMITS column carefully - the units differ.** A sankey is capped on
|
|
12
|
+
EDGES and a chord on NODES, so `<=80 edges` is a tighter constraint than `<=30 nodes`
|
|
13
|
+
on the same picture, not a looser one.
|
|
14
|
+
|
|
15
|
+
| chart | needs | limits | renderers | good for |
|
|
16
|
+
| --- | --- | --- | --- | --- |
|
|
17
|
+
| 3D scatter plot | 3 continuous | needs 360x300 px | D3, Plotly | Three continuous measures whose joint structure is the question, on a tile large enough to turn. To read exact values off three or more measures, Pair plot (scatter matrix) and Parallel coordinates are both more precise |
|
|
18
|
+
| Animated bar chart | 1 categorical, 1 continuous, 5+ time points | <=40 categories, needs 360x300 px | D3 | Requires one categorical, one measure and a time column with 5 or more ordered periods; best for a leaderboard that changes over time (top products by year, teams by season, countries by decade) |
|
|
19
|
+
| Animated treemap | 2 categorical, 1 continuous, 3+ time points | needs 280x280 px | D3 | Requires a 2-level categorical hierarchy plus an additive measure observed at 3 or more ordered time points |
|
|
20
|
+
| Animated World Choropleth | 1 categorical, 3+ time points, geo: country-iso3/country-iso2/country-name | <=250 categories, needs 400x300 px | D3 | Best for a country-level measure observed at 3 or more ordered time points — watch how sales, users, or population shift across countries year by year |
|
|
21
|
+
| Annotated heatmap | 2 categorical, 1 continuous | <=20 categories, needs 320x280 px | D3, Matplotlib, Plotly, Seaborn | Requires two variables: categorical × categorical with values |
|
|
22
|
+
| Arc diagram | 2 categorical | <=50 nodes, needs 380x240 px | D3 | Best for 5-50 nodes and a sparse-to-medium-density set of pairwise relationships |
|
|
23
|
+
| Area chart | 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires ordered categories or time with a continuous variable |
|
|
24
|
+
| Autocorrelation plot | 1 continuous, 20+ time points | needs 280x280 px | D3, Matplotlib, Plotly, Statsmodels | Requires a datetime series with one continuous variable |
|
|
25
|
+
| Bar chart (horizontal) | - | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires one categorical and one numeric variable |
|
|
26
|
+
| Bar chart (vertical) | - | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires one categorical and one numeric variable |
|
|
27
|
+
| Basic Sankey | 2 categorical, 1 continuous | <=80 categories, <=80 edges, needs 320x240 px | D3, Plotly | Requires two categorical (nodes) and a continuous variable |
|
|
28
|
+
| Beeswarm chart | 1 categorical, 1 continuous | <=30 categories, needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Best for showing distribution density across small categorical sets. |
|
|
29
|
+
| Binned 2D heatmap | 2 continuous | needs 320x280 px | D3 | Best for dense scatter data where points overplot: thousands of observations of two continuous variables, where the question is where the mass is rather than where each point is |
|
|
30
|
+
| Binned bubble matrix | 1 continuous | needs 320x300 px | D3, Matplotlib, Plotly, Seaborn | Two banded/categorical axes (or two continuous variables split into ranges) plus an aggregatable size measure per cell, with optional independent color. Choose this over a continuous Bubble chart when raw points would overplot into a blob, or when the axes are naturally grouped |
|
|
31
|
+
| Bivariate USA Choropleth (by state) | 1 categorical, 2 continuous, geo: us-state-code/us-state-name | <=56 categories, needs 400x300 px | D3 | Best for two state-level measures that might disagree: revenue vs return rate, income vs cost of living, cases vs vaccinations - at least 24 states and two measures that do not simply track each other |
|
|
32
|
+
| Bivariate World Choropleth | 1 categorical, 2 continuous, geo: country-iso3/country-iso2/country-name | <=250 categories, needs 400x300 px | D3 | Best for two country-level measures that might disagree: wealth vs inequality, revenue vs margin, cases vs deaths - at least 24 countries and two measures that do not simply track each other |
|
|
33
|
+
| Box plot | 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires one continuous variable (plus optional category) |
|
|
34
|
+
| Bubble chart | 3 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Three continuous variables (x, y, size); one mark per row on continuous axes. If you want both axes grouped into bands with one aggregated bubble per cell, pick Binned bubble matrix instead |
|
|
35
|
+
| Bullet chart | 1 continuous, a reference value | needs 220x120 px | D3, PLOTLY | Best for actual-vs-target KPIs with thresholds (revenue vs goal, SLA vs target) — a denser, clearer replacement for gauges. |
|
|
36
|
+
| Bump chart | 1 categorical, 1 continuous, 3+ time points | <=15 categories, needs 320x280 px | D3, PLOTLY | Best for leaderboard/position dynamics: how a handful of regions, products, or teams change rank quarter to quarter. |
|
|
37
|
+
| Calendar heatmap | 1 continuous, 60+ time points | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires daily datetime data with associated numeric values; best for activity/contribution tracking over time |
|
|
38
|
+
| Candlestick chart | 4 continuous, 10+ time points | needs 280x280 px | D3, Matplotlib, Plotly | Best for financial or trading data. |
|
|
39
|
+
| Card | 1 continuous | needs 100x60 px | D3, Plotly | One numeric value that summarizes the dataset; small viewports |
|
|
40
|
+
| Card with embedded | 1 continuous | needs 200x120 px | D3 | One headline value that deserves one more channel beside it: attainment with its target, a metric with its history, a profile of a few comparable scores, or a total with its split across up to eight categories; small tiles |
|
|
41
|
+
| Card with multiple KPI | 2 continuous | needs 180x100 px | D3, Plotly | Multiple independent numeric metrics that should be surfaced together; KPI dashboards; long-narrow / short-wide viewports |
|
|
42
|
+
| Card with sparkline | 1 continuous | needs 140x80 px | D3, Plotly | One numeric metric trending over an ordered dimension; small viewports |
|
|
43
|
+
| Chord diagram | 2 categorical, 1 continuous | <=25 categories, <=30 nodes, needs 320x320 px | D3 | Requires matrix data showing bidirectional flows between entities; best for migration, trade, or relationship intensity data |
|
|
44
|
+
| Circular heatmap | 1 categorical, 1 continuous | <=60 categories, needs 280x280 px | D3, Matplotlib, Plotly | Requires two variables: one categorical/ordered, one continuous |
|
|
45
|
+
| Clustered heatmap | 2 categorical, 1 continuous | <=50 categories, needs 320x320 px | Plotly | Requires two variables for matrix values |
|
|
46
|
+
| Connected scatterplot | 2 continuous, 6+ time points | needs 300x300 px | D3, PLOTLY | Best for the joint trajectory of two related metrics over time (e.g. units vs revenue, unemployment vs inflation) where the path shape is the insight. |
|
|
47
|
+
| Custom small multiples | 1 categorical, 1 continuous | <=16 categories, needs 320x240 px | D3, Matplotlib, Plotly, Seaborn | Best when comparing patterns across categories. |
|
|
48
|
+
| Cycle plot | 1 continuous, 24+ time points | needs 320x280 px | D3, PLOTLY | Best for multi-year monthly/quarterly/weekly data where the question is seasonality vs trend ('is Q4 always highest, and is each Q4 growing?'). |
|
|
49
|
+
| Delta KPI | 2 continuous | needs 200x120 px | D3 | Two comparable measures, or one measure at two points in time - this period against last, actual against plan, after against before |
|
|
50
|
+
| Dendrogram (tree diagram) | 2 categorical, 1 continuous | <=60 leaves, needs 320x240 px | D3, Plotly | Best for 2-4 hierarchy levels with ≤ ~80 leaves |
|
|
51
|
+
| Density contour plot | 2 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires two continuous variables |
|
|
52
|
+
| Donut chart | 1 categorical | <=10 categories, needs 280x280 px | D3, Matplotlib, Plotly | Requires one categorical variable with proportions |
|
|
53
|
+
| Dumbbell chart | 1 categorical, 2 continuous | needs 280x280 px | D3, Plotly | Best for before/after or comparison scenarios. |
|
|
54
|
+
| ECDF plot | 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn, Statsmodels | Requires one continuous variable |
|
|
55
|
+
| Error band | 1 continuous | needs 360x240 px | D3 | Best for repeated measurements over time or over a continuous axis: latency trials, sensor readings, A/B metrics - anywhere the SPREAD matters as much as the average |
|
|
56
|
+
| Error bar plot | 1 categorical, 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires one continuous variable with error ranges |
|
|
57
|
+
| Event plot | 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires one continuous variable representing event times |
|
|
58
|
+
| Flippable multi-card | 1 continuous | <=12 categories, needs 180x120 px | D3 | Best when more headline numbers compete for one tile than fit at once: several measures side by side, or one or two measures paged through a small category, with the details on hover |
|
|
59
|
+
| Funnel chart | 1 continuous | <=12 categories, needs 280x280 px | D3, PLOTLY | Best for conversion/attrition pipelines: signup funnels, sales pipeline stages, checkout flow drop-off. |
|
|
60
|
+
| Gantt chart | 1 categorical, 2 temporal | <=60 categories, needs 420x260 px | D3 | Best for project and phase schedules: tasks with a start and an end date, optionally grouped by phase, workstream or owner |
|
|
61
|
+
| Gauge | 1 continuous, a bounded scale | needs 140x140 px | D3 | One value against a ceiling the data states - a percentage, a rate, or a measure that has a target |
|
|
62
|
+
| Grouped bar chart | 2 categorical, 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires one categorical, one subcategory, and one numeric variable |
|
|
63
|
+
| Heatmap | 2 categorical, 1 continuous | <=50 categories, needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires two variables: categorical × categorical or categorical × continuous |
|
|
64
|
+
| Hexbin plot | 2 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires two continuous variables |
|
|
65
|
+
| Histogram | 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires one continuous variable |
|
|
66
|
+
| Horizon chart | 1 categorical, 1 continuous, 12+ time points | needs 280x280 px | D3, Matplotlib, Plotly | Best for dense time series dashboards. |
|
|
67
|
+
| Horizontal/vertical span plot | 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires one continuous variable with ranges to highlight |
|
|
68
|
+
| Icicle plot | 2 categorical, 1 continuous | <=60 leaves, needs 320x240 px | D3, Plotly | Best for 2-4 levels of hierarchy with ≤ ~50 leaves; an alternative to a sunburst when horizontal/vertical scanning is preferred |
|
|
69
|
+
| Joint plot | 2 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires two continuous variables |
|
|
70
|
+
| KDE plot (1D & 2D) | 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn, Statsmodels | Requires one continuous variable (or two for 2D KDE) |
|
|
71
|
+
| Lag plot (scatter of value vs lag) | 1 continuous, 20+ time points | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn, Statsmodels | Requires a datetime series with one continuous variable |
|
|
72
|
+
| Line chart | 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | One or more continuous series over an ordered/temporal axis |
|
|
73
|
+
| Linear gauge | 1 continuous, a bounded scale | needs 180x50 px | D3 | One value against a ceiling the data states, in a short wide tile - percent complete, utilisation, progress to a target |
|
|
74
|
+
| Lollipop chart | 1 categorical, 1 continuous | <=50 categories, needs 280x280 px | D3, PLOTLY | Best as a cleaner bar replacement for ranking many categories by a single measure. |
|
|
75
|
+
| Marimekko / Mosaic plot | 2 categorical, 1 continuous | needs 320x280 px | D3 | Best for 3-10 outer × 3-10 inner categories with a positive measure |
|
|
76
|
+
| Motion bubble chart | 1 categorical, 2 continuous, 3+ time points | <=40 categories, needs 360x320 px | D3 | Requires one categorical whose members are the bubbles, two measures for position and a time column with 3 or more ordered periods; best for watching entities travel - plans by subscribers and churn, countries by wealth and lifespan, teams by cost and output |
|
|
77
|
+
| Multi-level Sankey | 3 categorical, 1 continuous | <=80 edges, needs 420x280 px | D3, Plotly | Requires three (or more) categorical and one continuous variable |
|
|
78
|
+
| Network diagram | 2 categorical | <=150 categories, <=80 edges, needs 320x280 px | D3, Matplotlib | Requires node and edge data (source-target pairs); best for relationship, dependency, or social network visualization |
|
|
79
|
+
| Normalized stacked bar chart | 2 categorical, 1 continuous | needs 280x280 px | D3 | Best with two categoricals and one additive measure when the question is what the composition is rather than how big the total is |
|
|
80
|
+
| North America (Bubbles) | lat/lon | needs 400x300 px | D3 | Best for point-located data with latitude and longitude columns: stores, cities, facilities, or events across North America, with a measure for bubble size and optionally a second measure or category for color |
|
|
81
|
+
| Origin-Destination Flow Map | lat/lon | needs 400x300 px | D3 | Best for movement between places: flight routes, shipping and trade lanes, migration, commutes or transfers, where each row names where something started and where it ended plus a measure of how much moved |
|
|
82
|
+
| Packed circles | 2 categorical, 1 continuous | needs 280x280 px | D3 | Best with one numeric measure plus 1-2 categorical groupings producing 20-150 leaves |
|
|
83
|
+
| Pair plot (scatter matrix) | 3 continuous | needs 480x400 px | D3, Matplotlib, Plotly, Seaborn | Requires at least two continuous variables |
|
|
84
|
+
| Parallel coordinates | 3 continuous | needs 280x280 px | D3, Plotly, Vega | Best for 4-8 numeric dimensions and up to ~1000 rows (heavier overlap with more) |
|
|
85
|
+
| Pareto chart | 1 categorical | <=30 categories, needs 320x280 px | D3, MATPLOTLIB, PLOTLY | Best for finding the vital few: defect/complaint/incident counts by cause, revenue concentration by product or customer (the 80/20 view) |
|
|
86
|
+
| Pie chart | 1 categorical | <=10 categories, needs 280x280 px | D3, Matplotlib, Plotly | Requires one categorical variable with proportions |
|
|
87
|
+
| Polar plot | 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly | Requires angle and radius (two continuous variables) |
|
|
88
|
+
| Progress ring | 1 continuous, a bounded scale | needs 160x160 px | D3 | One value against a ceiling the data states, in a small or square tile - percent complete, attainment, utilisation |
|
|
89
|
+
| Radar (spider) chart | 1 continuous | <=8 axes, needs 280x280 px | D3, Matplotlib, Plotly | Requires multiple continuous variables across categories |
|
|
90
|
+
| Range-compare time series | 1 continuous, 15+ time points | needs 480x320 px | D3 | Best for a single measure tracked over many dates when the story is a chosen window: drag the two handles to total a period and compare its endpoints, like revenue across a campaign or sensor readings around an incident |
|
|
91
|
+
| Regression plot (line with CI) | 2 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn, Statsmodels | Requires one continuous variable (with optional predictor) |
|
|
92
|
+
| Ridgeline plots | 1 categorical, 1 continuous | <=25 categories, needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Best with many observations per category. |
|
|
93
|
+
| Rose (Coxcomb) chart | 1 categorical | <=24 categories, needs 300x300 px | D3 | Best for cyclical or directional categories: wind direction, hour of day, month of year, compass sectors - anywhere the categories wrap around rather than running left to right |
|
|
94
|
+
| Rug plot | 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires one continuous variable |
|
|
95
|
+
| Sankey alluvial flow | 2 categorical, 1 continuous | <=10 categories, <=80 edges, needs 420x280 px | D3, Matplotlib, Plotly | Requires at least two categorical variables |
|
|
96
|
+
| Scatter plot | 2 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires two continuous variables |
|
|
97
|
+
| Seasonal decomposition | 1 continuous, 24+ time points | needs 320x360 px | Matplotlib, Plotly, Statsmodels | Requires a datetime series with one continuous variable and at least two full seasonal cycles |
|
|
98
|
+
| Slope chart | 1 categorical, 1 continuous, 2+ time points | <=40 categories, needs 280x280 px | D3, PLOTLY | Best for two-period change across many categories: YoY by region/segment, before/after comparisons, ranking shifts between two snapshots. |
|
|
99
|
+
| Spiral plot | 1 continuous, 12+ time points | needs 320x320 px | D3, PLOTLY | Best for long, finely-grained, strongly periodic series (years of daily data) where the cyclic pattern is the story. |
|
|
100
|
+
| Stacked area chart | 1 categorical, 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly | Requires ordered categories with multiple continuous series |
|
|
101
|
+
| Stacked bar chart | 2 categorical, 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires one categorical, one subcategory, and one numeric variable |
|
|
102
|
+
| Stem plot | 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly | Requires one continuous variable |
|
|
103
|
+
| Step plot | 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires ordered categories with one continuous variable |
|
|
104
|
+
| Streamgraph | 1 categorical, 1 continuous, 8+ time points | needs 280x280 px | D3, Plotly | Best with 3-12 categorical series and a continuous time axis with at least 15-30 evenly-spaced points |
|
|
105
|
+
| Strip plot | 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires one categorical and one continuous variable; jitter on the category axis prevents overplot at the same value. |
|
|
106
|
+
| Sunburst chart | 2 categorical, 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly | Requires hierarchical categorical data |
|
|
107
|
+
| Tabular with embedded | 1 categorical, 1 continuous | <=40 categories, needs 420x200 px | D3 | Best for a small set of items compared across several attributes at once (a forecast/roster/scorecard table) |
|
|
108
|
+
| Ternary plot | 3 continuous | needs 320x320 px | D3 | Three measures that add up to the same total on every row - product mix, budget allocation, vote share, channel split |
|
|
109
|
+
| Thermometer | 1 continuous, a bounded scale | needs 90x220 px | D3 | One value against a ceiling the data states, in a tall narrow tile - a sidebar rail or a column of KPIs down a page edge |
|
|
110
|
+
| Time series plot | 1 continuous | needs 280x280 px | D3, Plotly | Requires a datetime axis with at least one continuous variable |
|
|
111
|
+
| Trail | 2 continuous | needs 360x220 px | D3 | Best when a series has both a level and a weight: price with traded volume, sentiment with mention count, a metric with the sample size behind it |
|
|
112
|
+
| Treemap | 1 categorical, 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly | Requires hierarchical categorical data with values |
|
|
113
|
+
| US hex-tile cartogram | 1 categorical, geo: us-state-code/us-state-name | needs 400x300 px | D3 | Best with one row per US state and a single measure, when the question is which states are high or low rather than where they are |
|
|
114
|
+
| USA Choropleth (by state) | 1 categorical, geo: us-state-code/us-state-name | <=56 categories, needs 400x300 px | D3 | Best for state-level US metrics: sales, users, or population by state, any measure that varies by US state (keyed to state names or USPS codes) |
|
|
115
|
+
| USA Choropleth (by ZIP-3) | 1 categorical, geo: us-zip5 | <=42000 categories, needs 400x300 px | D3 | Best for regional US ZIP analysis: metrics by 3-digit ZIP prefix area, any measure that varies across US postal regions (keyed to 5-digit ZIP codes, grouped to their 3-digit prefix) |
|
|
116
|
+
| Variance chart (budget vs actual) | 1 categorical, 2 continuous, a measure naming itself budget/plan/target | <=60 categories, needs 360x240 px | D3 | One category or period column plus two measures where one names itself the reference - Revenue and Revenue Budget, Cost and Cost Plan, Attained and Quota; finance reporting, budget reviews, plan attainment |
|
|
117
|
+
| Violin plot | 1 continuous | needs 280x280 px | D3, Matplotlib, Plotly, Seaborn | Requires one continuous variable (plus optional category) |
|
|
118
|
+
| Voronoi treemap | 2 categorical, 1 continuous | <=50 cells, needs 320x280 px | D3 | Best for 5-30 categories with one non-negative measure; an alternative to a plain treemap when the organic look is desired |
|
|
119
|
+
| Waffle chart | 1 categorical, 1 continuous | <=6 categories, needs 280x280 px | D3, Matplotlib, Plotly | Best for showing part-to-whole relationships with small number of categories; more accurate than pie charts |
|
|
120
|
+
| Waterfall chart | 1 continuous | <=20 categories, needs 280x280 px | D3, Matplotlib, Plotly | Best for financial data showing contribution to total (revenue bridges, P&L analysis, budget variance) |
|
|
121
|
+
| What-if projection | 1 continuous, 6+ time points | <=4 categories, needs 420x280 px | D3 | A dated measure with at least six periods when the question is what happens next under an assumption the reader chooses - revenue against a target, headcount, subscribers; bind a What-If parameter measure to drive the rate from a slicer |
|
|
122
|
+
| Word cloud | 1 categorical | <=100 categories, needs 280x200 px | Matplotlib, Plotly | Requires text data or pre-computed word-frequency pairs; best for qualitative text exploration |
|
|
123
|
+
| World (Bubbles) | lat/lon | needs 400x300 px | D3 | Best for point or country-level data spanning more than one continent: offices, shipments, users or revenue by country, with a measure for bubble size and optionally a second measure or category for color |
|
|
124
|
+
| World Choropleth | 1 categorical, geo: country-iso3/country-iso2/country-name | <=250 categories, needs 400x300 px | D3, PLOTLY | Best for country-level metrics: sales, users, or population by country, any measure that varies by nation (keyed to country names or ISO codes) |
|
|
@@ -15,6 +15,56 @@ run time, no per-render cost, and no network call. `@bicharts/chart-host` runs i
|
|
|
15
15
|
generates it. Generation happens **once, at build time, by you** — never in your users'
|
|
16
16
|
browsers.
|
|
17
17
|
|
|
18
|
+
## 0. Decide what to pull (only if you are starting from a data MODEL)
|
|
19
|
+
|
|
20
|
+
Skip this if you already have a table. If you are holding a semantic model, a warehouse schema or
|
|
21
|
+
a database, **you** pick the fields — the tools take a table, not a model, and they cannot see
|
|
22
|
+
what you can. Three decisions, and the third is the one that goes wrong.
|
|
23
|
+
|
|
24
|
+
**Fields and filters** follow from the question. *"All loans over the last 6 months, highlighting
|
|
25
|
+
those which defaulted, paying attention to credit score"* wants `LoanId`, `Defaulted`,
|
|
26
|
+
`CreditScore`, filtered to six months.
|
|
27
|
+
|
|
28
|
+
**A highlight is a COLUMN, not a styling note.** "Highlighting those which defaulted" means
|
|
29
|
+
`Defaulted` travels as its own categorical column. There is no instruction channel that can colour
|
|
30
|
+
rows the data does not distinguish.
|
|
31
|
+
|
|
32
|
+
**GRAIN is a choice, and the default is usually wrong for these charts.** Almost every BI query
|
|
33
|
+
aggregates — `GROUP BY`, `SUMMARIZECOLUMNS`, a pivot. But that sentence is asking about *the
|
|
34
|
+
distribution of individual loans*, which needs **one row per loan**. Aggregate it and you get a
|
|
35
|
+
clean bar chart of average credit score by default status: a valid chart, answering a different
|
|
36
|
+
question, and nothing downstream will flag it. Ask yourself which you meant:
|
|
37
|
+
|
|
38
|
+
| you want | pull | you get |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| how do individual loans spread out | **one row per loan** | beeswarm, strip plot, scatter, histogram |
|
|
41
|
+
| how do the groups compare on a total | one row per group | bars, treemap, pie |
|
|
42
|
+
| how does it move over time | one row per period (per series) | lines, area, streamgraph |
|
|
43
|
+
|
|
44
|
+
**Aim with `CHART-SHAPES.md`** (beside this file). It lists every chart the engine can build and
|
|
45
|
+
what each one needs — minimum columns by role, category ceilings, draw caps, viewport floors,
|
|
46
|
+
which renderers can draw it. It is GENERATED from the chart catalogue, so it cannot drift from what
|
|
47
|
+
the engine will actually accept. Read the LIMITS column carefully: **the units differ** — a sankey
|
|
48
|
+
is capped on EDGES and a chord on NODES, so `<=80 edges` is the tighter constraint on the same
|
|
49
|
+
picture, not the looser one.
|
|
50
|
+
|
|
51
|
+
**Then profile before you commit.** `assess_data_shape` is free, local, and needs no credentials —
|
|
52
|
+
it never leaves your machine. Run it on a candidate pull, look at what came back, and adjust the
|
|
53
|
+
query until the shape is what you meant. Only then spend a metered `list_eligible_charts` call.
|
|
54
|
+
Getting the grain wrong is cheap to fix here and expensive to fix after generation.
|
|
55
|
+
|
|
56
|
+
**When several charts genuinely fit, ASK — do not quietly pick one.** A shape that supports a
|
|
57
|
+
beeswarm often supports a violin, a box plot and a strip plot too, and those answer subtly
|
|
58
|
+
different questions. Say what you found and let the person choose:
|
|
59
|
+
|
|
60
|
+
> Your data supports a few readings. A **beeswarm** shows every loan as a point (best if you want
|
|
61
|
+
> to see individual outliers); a **violin** shows the shape of each group's distribution; a **box
|
|
62
|
+
> plot** is the most compact if you mainly want medians and spread. Which do you want?
|
|
63
|
+
|
|
64
|
+
The exception is when the request already names one, or when only one type survives — then just
|
|
65
|
+
build it. The rule exists because silently choosing is how a user ends up with a valid chart that
|
|
66
|
+
answers a question they did not ask.
|
|
67
|
+
|
|
18
68
|
## 1. Scaffold (one command block)
|
|
19
69
|
|
|
20
70
|
```bash
|