Appendix D — Chart names, translated

gog has no chart-type atoms: a histogram is a sentence, not a word. But people look for plots by name, so this appendix is the index of names. It is the one place organized by chart name; the cookbook organizes the same territory by question, which is usually the better place to start.

Column names here are placeholders: put your own in their place.

D.1 Names with a one-line answer

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 draw it sideways
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) for redundant encoding
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’s standard error, a standard error of measurement)
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 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) shades 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 stays flat between categories 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(note)
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 same centers the zone computed
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 has too many levels for a legend. 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 contours of a density estimated over the plane; density(levels = ) says how many, group(category) estimates one field per group. zone * density(levels = ) fills the bands between the same lines, and a crater (a ring-shaped cluster with a hollow middle) is the one field that filled reading draws wrongly, since a band around a hollow is a shape with a hole and gog has no mark for one
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 stops the eye reading the mesh’s own alignment 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
Choropleth zone with group(country) and map(): the boundary is the fifth way a zone finds its sides (Map)
Candlestick / OHLC chart two layers over one table, worked example in Zone: interval * bounds(low, high) + color(dir) is the whisker 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 replace a zone default meant for highlighting: 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 start at 0, and left/right sit just inside each slot’s edges, which is what leaves a gap 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 no scale gives its size a meaning

D.2 Names that need more

These names need a paragraph rather than a line. Nearly all of them draw, and the entry gives the sentence. Where one does not, the entry says so first and then says what the near miss costs you.

The name The sentence, and what to know
Box plot box + x(group) + y(value), the five-number summary per group
Violin plot 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 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 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 leave their own slots, which is the joyplot’s look. Its edge is a layer: line * density + style(color = "black") reads the same estimate and traces the edge of the fill
Jittered strip plot point * jitter + x(group) + y(value), the jitter collision modifier spreads coincident points along the category axis
Labeled scatter, names not overlapping point + text * repel + x(a) + y(b) + label(name), the repel collision modifier moves each word off the other words and off the dots, and draws a thin line back to the point when a label has moved far
Stacked bars / areas 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 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 area * stack(baseline = "wiggle") + x(t) + y(v) + color(g), worked through in Transforms. The foot of each pile is placed to keep the bands as flat as possible, 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 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 its designers argue readers compare values more accurately on the streamgraph (Byron & Wattenberg, 2008)
Alluvial diagram ribbon * flow(a, b, c) + y(count), with zone * flow(...) for the stage slots and text * flow(...) + label(name) for their names, worked through in Flow. One row of the table is one path through the stages, and one band carries that path’s magnitude between each adjacent pair
Sankey diagram Not drawn in the general form. The alluvial gives the merged-band look: group the table down to one pair of stages at a time and the bands are the flows between them. The general many-source form, nodes and links given as an edge list, is a different input shape and is not read (Flow says where the limits are)
Network diagram / node-link graph edge * layout(from, to) + network(), with point * layout(...) for the nodes, size(degree) sizing each node by its relations, and text * layout(...) + label(name) for their names, worked through in Network. The engine computes every position, so the picture is the same in all four languages; state an angle, network(turn = 35, tilt = 20), and the same layout is a cube that drags in the web edition
Relative-frequency histogram 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, so zone * bin counts the rows per cell: both axes for the classic heatmap, one for the mixed mesh. zone * density estimates a value at each cell of a plane. A categorical axis arrives cut, so on two of them zone * count tallies into the slots, and zone + color(value) draws a table you already have
Summary heatmap / matrix of means 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 zone + x(a) + y(b) + color(value), one cell per pair of categories, filling the slot each one owns
Confusion matrix 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 not one of these: stack(share = ) divides a pile by its slot’s total, and a grid has no pile to divide
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
Donut chart 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
Animated (time-lapse) chart any sentence + play(year): faceting read in time
Marginal / joint plot (scatter with histograms in its margins) 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
Dendrogram / cluster tree path * cluster(value, over = profile) + x(leaves) joins the closest leaves one pair at a time, with each join’s distance on an axis of its own; y(leaves) lays it on its side (Cluster). Dendrogram is Greek for tree drawing, which is what cluster tree says in English
Clustered heatmap zone * cluster(over = profile) reorders a tile plot’s slots to the tree’s leaf order, and the full figure is the marginal plot, with trees above and beside the tiles; the shared axes take the trees’ order (Cluster)
3-D surface The same sentence as Surface plot above, surface + x(a) + y(b) + z(c) over a grid table, or surface * density + x(a) + y(b) + 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) 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 a name that is listed. Ask what question the chart answers, and start from the cookbook. If you came from ggplot2 and the name was one of its function names, Coverage is the same territory indexed that way. It sorts each name into four: refused, the host language’s job, missing with the direction settled, and not decided either way.