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 covers the same plots organized by question, which is usually the better place to start.
The column names in these sentences are placeholders, such as a, b, category and measure. Replace them with columns from your own table. Three names are not placeholders, because gog computes those columns for you: depth, degree, and name after partition, flow or layout.
D.1 Names with a one-line answer
Each of these names is answered by one gog sentence. The left column is the name you know, and the right column is the sentence that draws it. Where a name needs a note as well, the note follows the sentence in the same cell.
| The name you know | The sentence |
|---|---|
| Scatterplot | point + x(a) + y(b) |
| Bubble chart | point + x(a) + y(b) + size(c) |
| Labeled scatter, names not overlapping | point + text * repel + x(a) + y(b) + label(name), where the repel collision modifier moves each label off the other labels and off the dots. When a label has moved far, repel draws a thin line back to its point |
| Strip plot | point + x(category) + y(measure), or swap the axes to draw it sideways |
| Jittered strip plot | point * jitter + x(category) + y(measure), the strip plot with each point moved a little along the category axis, so that points with the same value stop covering each other. The measured value does not move |
| Beeswarm | point * dodge + x(category) + y(measure), the strip plot with each point moved sideways only as far as it must to touch no other point, so the outline of each group shows its distribution. The measured value does not move (Point) |
| Dot plot | point * bin * stack + x(measure), one dot per row, piled above the bin it falls in (Transforms) |
| Bar chart / column 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"/"stripes"/"grid"/"dots" |
| Count (frequency) chart | bar * count + x(category) |
| Proportion chart | bar * proportion + x(category) |
| Histogram | bar * bin + x(measure); bin(30) sets the number of bins and bin(width = 5) sets their width |
| Relative-frequency histogram | bar * bin * proportion + x(measure), the histogram with each bar’s count divided by the number of rows, so the bars add up to 1. The bins stay where bar * bin puts them |
| 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) |
| Box plot / box-and-whisker plot / schematic plot | box + x(category) + y(measure), Tukey’s box plot per category: quartiles, median, whiskers, and each outlier drawn as a dot (Box) |
| Range bar | box(whiskers = "range") + x(category) + y(measure), the whole five-number summary per category: whiskers to the smallest and largest values, with no value drawn as a separate dot. Mary Eleanor Spear drew the box this way in 1952 (Box) |
| Violin plot | ribbon * density + x(category) + y(measure), the whole distribution that a box plot reduces to a few numbers. By default each violin’s area follows its category’s row count; density(compare = "shape") gives every violin the same area |
| Half violin | area * density + x(category) + y(measure): the same estimate, closed on the slot’s center line instead of on its own mirror image, so it draws one half of the violin |
| 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 * count * cumulative(share = TRUE) + x(measure): count tallies each distinct value, and cumulative adds the tallies up and ends at 1. color(group) draws one curve for each group (Transforms). A table that already holds the shares draws with step + x(measure) + y(share) (Step) |
| Running total / cumulative sum | line * cumulative + x(time) + y(measure), each position added to the ones before it; with color(group), each group adds up its own total (Transforms) |
| Ogive / cumulative frequency curve / cumulative histogram | step * bin * cumulative + x(measure), the number of rows in each bin and every bin to its left; bar * bin * cumulative draws the same counts as bars (Transforms) |
| Survival curve (Kaplan–Meier) / failure plot | step + x(time) + y(survival), over survival probabilities you computed in your host language: the curve holds its value between events and drops at each one. Start the table with a row at time 0 and survival 1, or the first drop is not drawn (Step) |
| Area chart | area + x(a) + y(b) |
| Spread / range band | ribbon * range + x(a) + y(b), split by group with color(group) |
| Fan chart | x(a) + y(b) + ribbon * range(0.1, 0.9) + ribbon * range(0.25, 0.75) + line * median, two bands of quantiles nested around the median. Give each layer its own style(color = , opacity = ), as the worked example does (Ribbon) |
| 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), two ends you already hold as columns, such as an estimate plus and minus 1.96 standard errors |
| Unfilled (dashed) error band | line * bounds(lower, upper) + x(a) + style(pattern = "dashed"), the upper and lower edges drawn as two lines, with nothing filled between them |
| Min–max envelope, as two lines | line * range + x(a) + y(b), the unfilled counterpart to ribbon * range |
| Error bar | interval * confidence(0.95) + x(category) + y(measure), one whisker per category, with a dot at each category’s mean. The transform says what the whisker measures. confidence gives a confidence interval, deviation one standard deviation each side of the mean, range the extremes, and bounds(lower, upper) two ends you computed yourself (Interval) |
| Pointrange | the error bar above, unchanged: confidence and deviation compute a mean, and interval draws a dot there. range and bounds compute no center, so they draw no dot (Interval) |
| Linerange | any interval sentence + style(caps = FALSE), the whisker without the short lines across its ends. With confidence or deviation, write style(caps = FALSE, center = FALSE) to remove the dot too |
| Coefficient plot | interval * bounds(lo, hi) + y(term), one whisker for each model term, with its two ends read from two columns you already have (Interval) |
| Dashed / dotted line | any line/step + style(pattern = "dashed") (or "dotted") |
| Trend line / smoother / LOESS | line * smooth + x(a) + y(b) |
| Trend line with a confidence band | x(a) + y(b) + ribbon * smooth_band + line * smooth |
| Regression line / line of best fit | line * straight + x(a) + y(b), the least-squares line (Transforms) |
| Regression line with a confidence band | x(a) + y(b) + ribbon * straight_band + line * straight |
| Reference line / threshold line | + data(thresholds) + rule, layered over the plot. thresholds has one column with the same name as the plot’s x or y column, and each row draws one line across the panel (Rule, Above and below a reference) |
| Rug | + rule + x(measure) + style(reach = "edge"), layered over the plot: one short tick per row, at its value, along the bottom edge of the panel. y(measure) puts the ticks up the left edge instead (Rule) |
| 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), where * dodge gives each group its own bar side by side inside the category’s slot |
| Colorblind-safe grouped bars | add + pattern(group) to the grouped bars: one column sets both the color and the hatch, so the two share one merged legend |
| Stacked bars / areas | bar * sum * stack + x(category) + y(measure) + color(group), the groups piled on top of each other inside each category’s slot. area in place of bar stacks areas, and grouped bars write dodge in place of stack |
| Ranked bars | add + order(measure, desc = TRUE) |
| Cleveland dot plot | point + y(category) + x(measure) + order(measure, desc = TRUE), the ranked bars with point in place of bar. Points need no zero on the axis, so small differences spread across the panel (Comparing categories) |
| Lollipop chart | y(category) + x(measure) + interval * bounds(zero, measure) + style(caps = FALSE) + point, a stem from zero and a dot at the value, over a table with a column of zeros added in your host language (Comparing categories) |
| Dumbbell chart | y(category) + x(measure) + interval * range + style(caps = FALSE) + point + color(time), over two rows per category, one for each time. color(time) comes after point, so it colors only the points; written before the marks, it would split each range into two lines of no length (Comparing categories) |
| Slope chart | x(time) + y(measure) + line + group(category) + point, over two rows per category, with time as text so the axis has two slots (Comparing categories) |
| Bump chart | x(time) + y(rank) + color(category) + path + point, over a table where each time’s rank was computed in your host language and stored as text with a declared order, 1st first, and each category’s rows in time order. line refuses a categorical y, and path joins the points in row order (Comparing categories) |
| Diverging lollipop chart | y(category) + x(measure) + interval * bounds(reference, measure) + style(caps = FALSE) + point, the lollipop chart with each stem starting at a reference value instead of at zero, over a table to which you add, in your host language, a column that holds the reference in every row (Above and below a reference) |
| Diverging bar chart | bar + y(category) + x(difference) + color(side), over a table with two columns computed in your host language: difference, each value minus the reference, and side, the side of the reference it falls on. A bar runs from zero to its value, so the bars below the reference run left (Above and below a reference) |
| Small multiples / trellis / conditioning plot / facets | plot | facet(category) puts the panels side by side, plot / facet(category) puts them one above another, and both together make a grid |
| Animated (time-lapse) chart | any sentence + play(year): one frame for each value of year, shown one after another, where a facet would show them side by side |
| Small multiples of 3-D plots | any 3-D sentence | facet(category): each panel holds its own cube, all drawn from the same angle |
| 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, so every a value is paired with every b value. style(border_color = "white") draws the mesh lines, and color(c) shades the sheet by height |
| Terrain / elevation / bathymetry | the same sentence: a height over a plane is a surface, whatever the height means |
| Response surface | surface + x(a) + y(b) + z(response) over the design grid, with a and b stored as numbers, because a surface refuses a categorical column. From a fitted model, predict onto a grid first and name that table in the sentence |
| 3-D density surface | surface * density + x(a) + y(b) + space(), the estimate raised as height. zone * density paints the same estimate as colored cells, and path * density traces it as contour lines |
| Profile plot (categories joined) | line * mean + x(category) + y(measure), one mean per category, joined by a line; step stays flat between categories instead of sloping |
| Filled profile | area * mean + x(category) + y(measure), the same boundary filled to the baseline |
| Parallel coordinates plot | line + x(measurement) + y(value) + group(id) + color(category), over a table with one row for each observation and measurement, so each observation is one line across the measurements. When the units differ, standardize each measurement first, to a mean of 0 and a standard deviation of 1. line * mean on top draws each category’s mean line, and polar() closes each line into a star (A third variable, and more |
| 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: when the row order in the table is the reading order, the mark 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 / polar area diagram / wind rose | bar * count + x(direction) + polar(), the bar chart read in a circle. The count sets each wedge’s radius, so a count twice as large gets four times the area; Nightingale’s polar area diagram put her value, a death rate, in the area instead (Polar) |
| Radar / spider / star plot / Kiviat diagram | line * mean + x(category) + y(measure) + polar(), the profile bent into a circle; area fills it |
| Radar band | ribbon * range + x(category) + y(measure) + polar(), a band around the circle from each category’s lowest value to its highest (Polar) |
| Pie chart | bar * count * stack + color(category) + polar(), a stacked bar in polar coordinates; the category is a split, not a position |
| Pie of a measure | bar * sum * stack + y(amount) + color(category) + polar(); write sum * proportion in place of sum for shares on the axis |
| Share-of-total column | the same sentence without polar(), one segmented bar |
| Treemap | bar * sum + y(value) + color(category) + nest(), the pie of a measure’s shares, carried by area rather than by angle (Nest) |
| Nested treemap | the same, plus x(group): one region per group, its rows packed inside |
| A pie for each group | bar * sum * stack(share = TRUE) + y(amount, axis = FALSE) + color(category) + polar() | facet(group), one pie per panel. stack(share = TRUE) makes each pie a whole circle; with plain stack the panels share one axis and the pies of the smaller groups are only part of a circle (Parts of a whole) |
| Polar histogram | bar * bin + x(bearing) + polar(), bins as wedges of a measured angle |
| Circular (cyclical) line | line + x(hour) + y(measure) + polar(). The line closes into a loop only when the table holds both ends of the cycle, such as hour 0 and hour 24 |
| 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 contour lines, and 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), eight bands on the levels a path traces. Each band is filled with its holes cut out, so a ring of points leaves its middle unpainted |
| 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 binned heatmap with hexagons for cells. Hexagons form no straight rows or columns, so the grid itself cannot be mistaken for a pattern in the data |
| Heat strip / binned distribution per group | zone * bin + x(measure) + y(category), the mixed mesh: the continuous axis cut into cells, one row of cells per category. Every row is cut on the same edges, so the cells line up down the plot |
| Tile plot / calendar heatmap | zone + x(a) + y(b) + color(value), one cell per pair of categories, each cell as wide and as tall as its two categories’ slots |
| Mosaic plot / Marimekko chart | zone * partition(a, b, cross = TRUE) + x(measure) + color(b) + style(border_color = "white"): a divides the width, and b divides the height inside each of those columns. The white border shows where one cell ends and the next begins, even when the two have the same color (Transforms; with commutes, in Parts of a whole) |
| Spine plot | zone * partition(a, cross = TRUE) + x(measure) + style(border_color = "white"), the mosaic with one level: one column per category, as wide as its share, with nothing dividing it (Transforms) |
| Choropleth | zone with group(country) and map(): group says which rows belong to one region, and the region’s own boundary becomes the zone’s sides (Map) |
| Proportional-symbol map | point + x(lon) + y(lat) + size(measure) + map(), the bubble chart’s sentence in the map space, usually drawn over a boundary table with path (Map) |
D.2 Names that need more
These names need a paragraph rather than a line. gog draws each of them, and the entry gives the sentence and what to know about it.
| The name you know | The sentence, and what to know |
|---|---|
| Ridgeline plot / joyplot | area * density(reach = 2.5) + x(measure) + y(category), the half violin with its axes exchanged: one density per category, each rising from its own category’s place on the y axis, all sharing one measure axis. reach is measured in slots, from a category’s line to the top of the tallest ridge. Above 0.5 that ridge reaches into the next category’s slot, and at 2.5, as here, the ridges overlap, which is what makes a joyplot. To outline it, add a layer: line * density(reach = 2.5) + style(color = "black") reads the same estimate, with the same reach, and traces the top of the fill |
| 100% stacked bar / filled area | bar * count * stack(share = TRUE) + x(a) + color(b), every pile is divided by its own slot’s total. Each pile then reaches 1, so the plot shows composition and no longer shows size. y(count, percent = TRUE) writes the axis’s numbers as 0% to 100%. Other summaries work the same way: bar * sum * stack(share = TRUE) with a y column, and area * sum * stack(share = TRUE) for the filled area |
| Streamgraph | area * stack(baseline = "wiggle") + x(t) + y(v) + color(g), worked example in Transforms. The foot of each pile is placed so that the bands move as little as possible, the thickest bands least of all. A thick band’s shape then shows its own values rather than the movement of the bands under it. share and baseline are the pile’s two independent choices, and you can use them together |
| ThemeRiver | area * stack(baseline = "center"), the same sentence with the symmetric layout instead (Havre et al., 2000). Readers often confuse it with the streamgraph, and it is a different plot. This one centers every pile, while the streamgraph keeps its bands as flat as possible. The streamgraph’s designers argue that readers compare values more accurately on it (Byron & Wattenberg, 2008) |
| Alluvial diagram | ribbon * flow(a, b, c) + y(amount), with zone * flow(...) for the stage slots and text * flow(...) + label(name) for their names, worked example in Flow. Each row follows one path through the stages, and rows on the same path are merged into one band, as thick as their total. Bind the amount to x instead, x(amount), and the stages run from top to bottom. A stage in color() colors each band by its place at that stage, and any other categorical column in color() splits each band into one part for each value |
| Sankey diagram | ribbon * flow(source, target, layered = TRUE) + y(amount), with zone * flow(...) for each place’s slot and text * flow(...) + label(name) for its name, worked example in Flow. Each row is a link from one place to another, and layered = TRUE puts each place in the first layer after every place that sends to it, so a band can skip a layer, and a flow can stop before the last layer. The amounts that arrive at a place are added up there, so a band cannot be followed past it. When every row passes through the same stages in order, the alluvial sentence above keeps each path. Links that form a cycle are refused |
| Arc diagram | ribbon * flow(a, b, shared = TRUE) + x(amount), with zone * flow(...) for each place’s slot and text * flow(...) + label(name) for its name, worked example in Flow. shared = TRUE says the two columns name one set of places, so each place is one slot on one axis. A slot’s length is the total the place sends and receives. It has two parts, with no line between them: what the place sends, then what it receives, in a darker shade. Each band is an arc from one place to another. The axis carries no numbers, and the names are written where the numbers would be. With the amount on y the axis runs up the page |
| Chord diagram | The arc diagram’s sentence with polar() added: ribbon * flow(a, b, shared = TRUE) + x(amount) + polar(), worked example in Flow. Each place is a piece of the ring, and each band curves toward the center. A band’s area depends on how far apart its places are on the ring, so read a band at its two ends, or one place at a time with brush(name, at = ...). A flow with stages in polar() is a different picture, and gog refuses it with a message |
| Network diagram / node-link graph | edge * layout(from, to) + network() draws the edges, worked example in Network. point * layout(...) adds the nodes, size(degree) draws a node larger when it appears in more rows, and text * layout(...) + label(name) writes their names. State an angle, network(turn = 35, tilt = 20), and gog lays the nodes out again in a cube, which the reader can turn with a drag in the web edition. The text layer names the nodes there too (Network) |
| Heatmap | A heatmap is drawn on two continuous axes, on two categorical axes, or on one of each. The transform you need depends on which kinds you have. A continuous axis needs cutting, so zone * bin counts the rows per cell: both axes for the classic heatmap, one for the mixed mesh. A categorical axis is already divided into slots. On two categorical axes, zone * count tallies the rows into those slots, and zone + color(value) draws a table you already have. zone * density is one more route, for two continuous axes: it estimates a value at each cell of the plane rather than counting rows |
| Summary heatmap / matrix of means | zone * mean + x(a) + y(b) + color(column) reduces the named column inside every cell where two categories cross, and sum/median/max/min read the same mesh. The column is named on color because a zone shows its measurement as color, and the mean is drawn on that same channel. On two continuous axes, cut them into cells first: zone * bin * mean |
| 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 means a share within each column of this grid, one column per actual class, and neither transform does that. Compute those shares in your host language and draw them as a tile plot: zone + x(actual) + y(predicted) + color(share) |
| Correlation matrix / corrplot | Drawn as a tile plot, once the correlations are a table. Compute them in your host language, then reshape the result so that each row holds one pair of variables and their correlation. zone + x(var1) + y(var2) + color(r) draws that table |
| Sunburst | zone * partition(a, b, c) + x(measure) + color(a) + style(border_color = "white") + polar(), worked example in Polar. One ring per level of a tree, each arc as wide as its share. The hierarchy is columns, named from the top of the tree down, so the first column is the innermost ring. A missing value in a level ends that branch early, so the branch does not reach the outer ring. The outer edge of the plot is then uneven. y(depth, limits = c(0, k + 1)), for a tree k levels deep, puts the hole in the middle, and text * partition(a, b) + 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 only difference: depth up the y axis, share across the x. One polar() separates the two names, exactly as it separates a rose from a bar chart, or a pie from a stacked bar |
| Donut chart | zone * partition(category) + x(measure) + y(depth, limits = c(0, 2)) + color(category) + polar(), worked example in Polar. A donut is a sunburst of a tree one level deep. Its one ring is between 1 and 2 on depth, so limits = c(0, 2) leaves the inner half of the radius empty, and that empty part is the hole. The plain pie (bar * count * stack) cannot have a hole, because it binds nothing to the radius |
| Labeled treemap | bar + y(value) + color(category) + text + label(name) + nest(), over a table with one row per region. Each name is written at the center of its own region, which helps when there are too many regions for a legend. The text layer does not follow a sum in the bar layer, so with bar * sum the names land in the wrong regions. To name summed regions, sum the table in your host language first. A name that does not fit inside its region is drawn smaller, at the size that fits (Nest) |
| Back-to-back bar chart / butterfly chart | bar * sum + y(category) + x(measure) + color(group), over a table where one group’s counts were made negative in your host language, so its bars run left of zero. sum adds up the rows that share a category and a group. A table with one row for each, like the population pyramid below, needs no sum (Above and below a reference) |
| Population pyramid | bar + y(age) + x(population) + color(group) + order(age, desc = TRUE), over a table where one group’s populations were made negative in your host language, so its bars run left of zero. age needs its declared order, youngest first, and desc = TRUE puts the youngest band at the bottom (Many groups) |
| 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). Compute body_lo, body_hi, dir, left and right in your host language, as the worked example does. One session gives four numbers, and gog needs no new channel to carry them. bounds reads a low value and a high value, and a rectangle’s bottom and top are the same two numbers. A zone whose sides you name is translucent, because a rectangle you chose is usually a highlight. Here the rectangle is the data, so style(opacity = 1) draws it solid, and left and right make each body narrower than its slot |
| Waterfall / bridge chart | zone * bounds(base, top, start = left, end = right) + x(step) + color(dir) + style(opacity = 1), worked example in Zone. Each block starts at the total before it, so its length is the change in its step. cumulative draws each total from zero, so compute where each block starts and ends in your host language, as new columns of the table. The subtotal blocks start at 0. left and right are just inside each slot’s edges, which is what leaves a gap between the blocks |
| Funnel chart | zone * bounds(lo, hi) + y(stage) + style(opacity = 1), with text + label(n) + x(mid) for the numbers inside, worked example in Zone. A funnel is a bar chart whose blocks are centered on zero. Compute lo and hi as -n/2 and n/2 in your host language, and mid as a column of zeros. The blocks lie across the page because y(stage) is a category, so the measure goes on x. gog draws no sloped connectors between the stages, because the space between two categories holds no data |
| Significance brackets / p-value stars | box + x(category) + y(measure), with two more layers over tables the host language builds from a statistical test: path + group(pair) joins the four corners of each bracket, and text + label(stars) + style(nudge = "up") writes the stars above the group compared, worked example in Coverage |
| Survival curve with a risk table | the Kaplan–Meier step above a second plot, text + x(time) + y(group) + label(at_risk), joined by / so that the two share the time axis. Name each group’s color in palette() in both plots, so the colors agree, and write legend = FALSE in the second (Coverage) |
| Direct labels / names at the line ends | line + x(time) + y(measure) + color(series, legend = FALSE), then a second table with one row per line, at its last time: text + label(series) + color(series) + style(nudge = "right"). Widen the time axis with limits so the names fit (Coverage) |
| UpSet plot | the count for each combination of sets as bar, above a grid of dots, point + x(combination) + y(set) + color(member), with path + group(combination) joining the sets in each combination. The host language counts the combinations and writes the tables (Coverage) |
| Horizon chart | area + x(time) + y(part) + color(band) + style(opacity = 1), one panel per series with / facet(series), over bands the host language cuts: each difference from a chosen value, split into slices of fixed height. List each lighter band before the darker one drawn over it, because a band is drawn in the order it first appears (Coverage) |
| Marginal / joint plot (scatter with histograms in its margins) | top / (main | right): three ordinary plots and the two composition operators (Composition). Each marginal lines up with the main plot because it names the same column on the same axis and reads it the same way, so a marginal over a log axis writes scale = "log" too. The top plot names the main plot’s x column, and the right plot names its y column. Along the top, a marginal can be a histogram, a density curve or a dot plot. Down the side, a histogram works (bar * bin + y(b)), and a density curve or a dot plot is refused. A box or a violin needs a category on its other axis, and then draws one per category |
| Dendrogram / cluster tree | path * cluster(value, over = profile) + x(item) joins the closest leaves one pair at a time. Each join is drawn at its distance on the other axis, which cluster fills and titles Distance. item is the column that names the leaves, and binding it to y instead lays the tree on its side (Cluster). Dendrogram comes from the Greek words for tree and drawing |
| Clustered heatmap | zone * cluster(over = profile) reorders a tile plot’s slots into the tree’s leaf order. The full figure is built like the marginal plot, with one tree over the tiles and one beside them, and each shared axis takes its tree’s order (Cluster) |
| 3-D surface | The same sentence as Surface plot / wireframe in the first table, 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. gog refuses it and names point instead of drawing an empty sheet, because a surface’s faces span the gaps between its samples. A surface needs its samples on a grid |
| Terraced / stepped surface (one value per cell) | surface * bin(3) * mean + x(a) + y(b) + z(v) cuts the floor into a 3 × 3 grid of cells and lays a flat plateau on each, with a vertical face at every step. This is the sentence for a design that measures one number per condition, here three levels on each axis. Give bin that number of levels: with more cells than conditions, empty cells separate the plateaus. An interpolated sheet would show a slope nobody observed (Surface) |
If the name you are looking for is in neither table, it is usually one of the listed plots with a different mark, transform or setting. Ask what question the chart answers, and start from the cookbook. If the name is one of ggplot2’s function names, the phrasebook gives the gog sentence for each call, and Coverage says which of those plots gog draws at all. Each plot that gog does not draw is in one of four groups there: refused, the host language’s job, missing with the direction settled, and not decided either way.