Appendix D — Chart names, translated

gog has no chart-type atoms (a “histogram” is a sentence, not a word), but chart names are how the world indexes its questions, so this appendix is the dictionary. It is the one place in the book organized by name; the cookbook organizes the same territory by question, which is usually the better door in.

D.1 Drawn today

The name you know The sentence
Scatter plot point + x(a) + y(b)
Bubble chart point + x(a) + y(b) + size(c)
Strip plot point + x(category) + y(measure), or swap the axes to lay it down
Bar chart bar + x(category) + y(measure)
Horizontal bar chart bar + x(measure) + y(category)
Hatched (print-safe) bars bar + x(category) + y(measure) + style(pattern = "hatch"), also "crosshatch"/"grid"/"dots"
Count (frequency) chart bar * count + x(category)
Proportion chart bar * proportion + x(category)
Histogram bar * bin + x(measure), bin(30) or bin(width = 5) to tune
Frequency polygon line * bin + x(measure)
Outline (step) histogram step * bin + x(measure)
Overlaid histograms bar * bin + x(measure) + color(group)
Density plot line * density + x(measure)
Line chart / time series line + x(time) + y(measure)
Multi-series lines by dash (no color) line + x(time) + y(measure) + pattern(series), add color(series) to double-encode
Step chart step + x(a) + y(b)
Empirical CDF step over cumulative shares, worked example in Step
Area chart area + x(a) + y(b)
Spread / range band ribbon * range + x(a) + y(b), split by group with color(group)
Confidence band (computed) ribbon * confidence(0.95) + x(a) + y(b), often under a line * mean trend
Confidence band (pre-computed) ribbon * bounds(lower, upper) + x(a), bounds you already have (a model SE, an SEM)
Unfilled (dashed) error band line * bounds(lower, upper) + style(pattern = "dashed"), the two ± edges, no fill
Min–max envelope, as two lines line * range + x(a) + y(b), the unfilled counterpart to ribbon * range
Dashed / dotted line any line/step + style(pattern = "dashed") (or "dotted")
Trend line / smoother / LOESS line * smooth + x(a) + y(b)
Summary bars (mean per group) bar * mean + x(category) + y(measure), also sum, median, max, min
Grouped bars (side by side) bar * mean * dodge + x(category) + y(measure) + color(group), * dodge separates the split
Colorblind-safe grouped bars add + pattern(group) to the grouped bars: hue and hatch, one merged legend
Ranked bars add order(measure, desc = TRUE)
Small multiples / trellis / conditioning plot / facets plot \| facet(category), plot / facet(category), or both for a grid
Small multiples of 3-D plots any cube sentence \| facet(category): one projected box per panel
3-D scatter point + x(a) + y(b) + z(c), view angle via space(turn = , tilt = )
3-D trajectory / space curve path + x(a) + y(b) + z(c), the rows joined in table order, in the cube
Surface plot / wireframe / persp surface + x(a) + y(b) + z(c) over a table with one row per (x, y) crossing (expand.grid()’s shape); style(border_color = "white") draws the mesh lines, color(c) ramps it by height
Terrain / elevation / bathymetry the same sentence: a height over a plane is a surface, whatever the height means
Response surface surface + x(factor1) + y(factor2) + z(response) over the design grid; from a fitted model, predict onto a grid first and hand over the result
3-D density surface surface * density + x(a) + y(b) + space(), the estimate raised as height, the third geometry of the same field zone * density paints and path * density traces
Profile plot (categories joined) line * mean + x(category) + y(measure), one summary per category with the path across them; step holds instead of sloping
Filled profile area * mean + x(category) + y(measure), the same boundary filled to the baseline
Connected scatterplot path + x(a) + y(b), the rows joined in the table’s order rather than sorted by x; style(arrow = "end") says which end is last
Trajectory / route / hysteresis loop the same sentence: any reading whose order is the data’s is path, not line
Annotation arrow / callout data(two_rows) + path + style(arrow = "end"), layered over the plot; the note itself is data(one_row) + text + label(what)
Rose / coxcomb / wind rose bar * count + x(direction) + polar(), the bar chart read in a circle
Radar / spider plot line * mean + x(category) + y(measure) + polar(), the profile bent into a circle; area fills it
Pie chart bar * count * stack + color(category) + polar(), a stacked bar in polar coordinates; the category is a split, not a position
Sunburst zone * partition(<a>, <b>, <c>) + x(<measure>) + polar(), worked example in Polar. One ring per level of a tree, each arc as wide as its share; the hierarchy is columns, outermost first, and a blank level ends that branch early, which is what gives the rim its ragged edge. y(depth, limits = c(0, n)) puts the hole in the middle, and text * partition(…) + label(name) names the nodes, reading the center the same computation published
Icicle / partition chart the sunburst’s sentence with polar() taken off, which is the whole difference: depth up the y axis, share across the x. The two names are one coordinate space apart, exactly as a rose and a bar chart are, or a pie and a stacked bar
Treemap bar * sum + y(value) + color(category) + nest(), the same shares carried by area rather than by angle (Nest)
Nested treemap the same, plus x(group): one region per group, its rows packed inside
Labeled treemap the same, plus a text layer: + text + label(name) writes each region’s name at its center, which is what a packing needs once the split is too wide for a legend to read. A name wider than the region it belongs to is left out, and the plot reports how many (Nest)
Pie of a measure bar * sum * stack + y(amount) + color(category) + polar(), also proportion for shares on the axis
Share-of-total column the same sentence without polar(), one segmented bar
Polar histogram bar * bin + x(bearing) + polar(), bins as wedges of a measured angle
Circular (cyclical) line line + x(hour) + y(measure) + polar(), both ends of the cycle in the data
Polar scatter point + x(bearing) + y(measure) + polar()
Contour plot / density contours path * density + x(a) + y(b), the iso-lines of a density estimated over the plane; density(levels = ) says how many, group(category) estimates one field per group
2-D density heatmap zone * density + x(a) + y(b), the same field painted as cells instead of traced as lines
Filled contour / filled density zone * density(levels = 8) + x(a) + y(b), the bands between eight contours; the same levels a path traces
Binned heatmap zone * bin + x(a) + y(b), cells colored by how many rows fell in each
Hexbin zone * bin(tiling = "hex") + x(a) + y(b), the staggered mesh that keeps the eye from reading the lattice as data
Heat strip / binned distribution per group zone * bin + x(<number>) + y(<category>), the mixed mesh: the continuous axis cut into cells, one row of them per category, every row cut on the same edges
Candlestick / OHLC chart two layers over one table, worked example in Zone: interval * bounds(low, high) + color(dir) is the wick and zone * bounds(body_lo, body_hi, start = left, end = right) + color(dir) + style(opacity = 1) the body, over x(session). Four numbers a session, and no new channels for them: the pair a band mark reads is the pair a rectangle’s sides are. The opacity and the named sides both overrule a zone default that assumes a highlight: here the rectangle is the data
Waterfall / bridge chart zone * bounds(base, top, start = left, end = right) + x(step) + color(dir) + style(opacity = 1), worked example in Zone. The running total is host arithmetic (cumsum), because stack accumulates within a position and a waterfall accumulates across positions; the subtotal bars that stand on the floor are rows whose base is 0, and left/right are the slot center ± a little, which is what puts air between the bars
Funnel chart zone * bounds(lo, hi) + y(stage) + style(opacity = 1), worked example in Zone, with text + label(n) + x(mid) for the numbers inside. The columns lo and hi hold -n/2 and n/2, computed in the host, which is the same arithmetic the waterfall uses for its running total. A funnel is a bar chart whose blocks are centered on zero, and centering is two columns rather than a chart type. The measure lands on x because y(stage) is a category; nothing had to ask for it. The sloped connectors between stages are deliberately absent. Each one spans the gap between two categories, where the axis means nothing, so its size is read off no scale

D.2 Asked for, and where each one stands

These names need more than one line to answer. Nearly all of them draw, and the entry gives the sentence. Where one does not, it says what is missing rather than drawing something else in its place.

The name Where it stands
Box plot ✅ drawn: box + x(group) + y(value), the five-number summary per group
Violin plot ✅ drawn: ribbon * density + x(group) + y(value), the shape the box plot’s five numbers summarize. density(compare = ) says whether the widths carry each group’s row count (the default) or draw every violin to the same area
Half violin ✅ drawn: area * density + x(group) + y(value): the same estimate closed on the slot’s center line instead of on its own reflection, which is the difference between those two marks everywhere else
Ridgeline plot / joyplot ✅ drawn: area * density(reach = 2.5) + x(value) + y(group), the half violin with its axes exchanged, one density per category, each on its own line, sharing one measure axis. reach is in slots, so past 0.5 the ridges run into the row above, which is the joyplot’s look. Its black edge is a layer, line * density reading the same slot reading and tracing what the fill fills
Jittered strip plot ✅ drawn: point * jitter + x(group) + y(value), the jitter collision modifier spreads coincident points along the category axis
Stacked bars / areas ✅ drawn: bar * sum * stack / area * sum * stack with a color split, the stack collision modifier (grouped bars are its sibling dodge)
100% stacked bar / filled area ✅ drawn: bar * count * stack(share = TRUE) + x(<a>) + color(<b>), every pile divided by its own slot’s total so all of them reach 1 and only the composition is left. Any measurement fills the same way, sum included
Streamgraph ✅ drawn: area * stack(baseline = "wiggle") + x(<t>) + y(<v>) + color(<g>), worked through in Transforms. The foot of each pile is chosen to make the bands as flat as it can, so a band’s shape is its own rather than the sum of everything below it. share and baseline are the pile’s two free choices and compose
ThemeRiver ✅ drawn: area * stack(baseline = "center"), the same sentence with the symmetric layout instead (Havre et al., 2000). Often confused with the streamgraph and not the same plot: this one centers every pile, that one minimizes movement, and readers compare values more accurately on the streamgraph (Byron & Wattenberg, 2008)
Relative-frequency histogram ✅ drawn: bar * bin * proportion + x(<number>), the histogram’s own counts read as fractions of n, on the mesh bar * bin cuts
Heatmap ✅ drawn on either kind of axis, and on one of each. Which transform you want depends on which: a continuous axis needs cutting and a categorical one arrives cut, so zone * bin counts the rows per cell wherever there is something to cut (both axes for the classic heatmap, one for the mixed mesh), zone * density estimates a value at each cell of a plane, and on two categorical axes zone * count tallies into the slots while zone + color(<value>) draws a table you already have
Summary heatmap / matrix of means ✅ drawn: zone * mean + x(<a>) + y(<b>) + color(<column>) reduces the named column within every cell two categories cross, and sum/median/max/min read the same mesh. The column is named on color because that is the channel a zone measures with, and a summary reduces in place, the same binding that both names and receives it on bar * mean + x + y
Tile plot / calendar heatmap ✅ drawn: zone + x(<a>) + y(<b>) + color(<value>), one cell per pair of categories, filling the slot each one owns
Confusion matrix ✅ drawn: zone * count + x(actual) + y(predicted) tallies the raw rows; zone * proportion reads them as shares of the whole. Normalizing per true class (a share within each row of the grid) is still not drawn: stack(share = ) answered the 100% stacked bar’s half of the margin question, but a grid has no pile to fill
Correlation matrix / corrplot ✅ drawn as a tile plot, once the correlations are a table: compute cor() where your data lives, reshape it long, and zone + x(var1) + y(var2) + color(r) draws it. gog computes no correlations; that is the host’s job, as x(sin(t)) is
Contour plot ✅ drawn both ways: path * density traces the iso-lines, zone * density(levels = ) fills the bands between them. A crater (a ring-shaped cluster with a hollow middle) is the one field the filled reading draws wrongly, since a band round a hollow is a shape with a hole and gog has no mark for one, so the traced form shows it correctly
Donut chart ✅ drawn: zone * partition(<category>) + x(<measure>) + y(depth, limits = c(0, 2)) + polar(), worked example in Polar. A donut is a sunburst of a tree one level deep, and the hole is not a round thing at all; it is a stretch of the radial axis with nothing standing on it, which is what the stated limits leave empty. The plain pie (bar * count * stack) is the one reading that cannot say it, having spent its measurement on the angle and left its radius a constant with no domain to widen; that is a fact about the reading rather than a gap, so there is no polar(hole = ) and no plan for one
Radar / spider plot ✅ drawn: line * mean + x(category) + y(measure) + polar(), filled with area; the path closes because a categorical angle wraps
Choropleth / geographic map half drawn, and the half that is missing is not the space. map() projects the earth and takes any mark that draws on a plane, so a quantity at a place is point + size(<value>) + map() (Map). The shaded region is what is owed: a choropleth needs a filled area whose boundary comes from the data, and none of the four ways zone finds its sides is a coastline
Animated (time-lapse) chart ✅ drawn: any sentence + play(year): faceting read in time
Marginal / joint plot (scatter with histograms in its margins) ✅ drawn: top / (main | right): three ordinary plots and the two composition operators. No chart type, no ggMarginal(): the marginals align and share their scale because both name the same column on the same axis, which is the one rule composition adds (Composition). Any mark can be the marginal: a histogram, a box, a violin, a dot plot
3-D surface ✅ drawn: surface + x + y + z over a grid table, or surface * density + space() to raise an estimated field. A scatter cannot be one, and is refused toward point rather than drawn as an empty sheet: a surface’s faces span the gaps between its samples, so it needs samples on a grid
Terraced / stepped surface (one value per cell) ✅ drawn: surface * bin * mean + x(a) + y(b) + z(v) cuts the floor into cells and lays a flat plateau on each, with a riser at every step. The sentence for a design that measures one number per condition, where an interpolated sheet would assert a gradient nobody observed (Surface)

If the name you came with is in neither table, it is usually a styling of one that is; ask what question the chart answers, and enter through the cookbook. If you came from ggplot2 and the name was one of its function names, Coverage is the same territory indexed that way, and says which of its features are refused, which are owed, and which nobody has decided about yet.