ggpbi — Grammar of Graphics for Power BI
My own open-source project · TypeScript & D3 · MIT licence · github.com/efelcie/ggpbi · Last updated
Power BI ships a fixed list of chart types. Anyone who needs something else reaches for an R or Python visual — those need an installed runtime and end up delivering an image: no cross-filtering, no native tooltips.
ggpbi takes the other route. It brings the grammar of ggplot2 to Power BI — fields map to aesthetics, geoms stack as layers — but as a native TypeScript/D3 visual. No runtime, no R, no Python. It renders as fast as any built-in visual and works in the Power BI Service.
A report like this is built by dropping fields into wells; the Format Pane writes the ggpbi chain from them. And the other way round: since version 0.5 the code view is a real editor, with an optional vim mode. What you change there writes back into the Format Pane — editor and pane are two doors into the same room. The editor speaks three languages: the ggpbi chain, ggplot2 in R, and ggpbir, the report’s JSON format.
And outside Power BI
ggpbi is an ES module with D3 underneath — Power BI is one of the places it runs, not the only one. Both charts on this page are drawn with it: the hours up in the skills section and the book matrix. And really with it — the code below is exactly what draws them, not a simplified example. The library is only fetched once the page is up; until then an SVG stands there, and it stays if anything goes wrong.
ggpbi() // the hours
.data(hours) // 2 x learning + practice
.aes({ x: 'Jahr', y: 'Gewichtet',
color: 'Skills' })
.geom('hline', { yintercept: 10000,
linetype: 'dashed' })
.geom('line', { size: 2 })
.size(640, 400)
.renderTo(element);
ggpbi() // the books
.data(books)
.aes({ x: 'Umfang', y: 'Wirkung',
color: 'Genre', label: 'Titelkurz' })
.scale({ x: { labels: () => '' },
y: { labels: () => '' } }) // no ticks
.geom('point', { size: 4, alpha: 0.72 })
.tooltip({ fields: ['Titel','Autor','Gelesen'] })
.geom('text', { repel: true, size: 10 })
.geom('vline', { xintercept: middle })
.renderTo(element);
repel pushes them apart until none
covers another.
What’s in it
Geoms: point, line, bar, col, area, text, boxplot, violin, histogram, density, smooth (lm, loess, moving average), segment, pointrange, plus the reference lines hline, vline and abline.
Grammar: aesthetics (x, y, color, fill, size, shape, alpha, group, label), positions (identity, stack, dodge, fill, jitter), scales (linear, log, sqrt, time, category) with locale-aware number and date formats, faceting by row and column, and gghighlight-style highlighting.
Power BI native: cross-filtering by click, native tooltips, context menu, report themes, high-contrast mode and style presets.
Two fields are enough to start: one in X, one in Y. ggpbi picks the geom from the scale types — number and number give a scatter plot, category and number a bar chart, date and number a line, a number on its own a histogram.
Status: version 0.5.0 — about 16,000 lines of TypeScript across 51 modules, 67 test files. Not on AppSource yet; it installs by file import in Power BI Desktop.
I ported the same core — scales, axes, label engine — to Elm, to see what survives of the grammar when the compiler flags every gap. The chart above is the TypeScript version.