| exporter | importer | billions |
|---|---|---|
| China | United States | 500 |
| Mexico | United States | 455 |
| Canada | United States | 420 |
| United States | Mexico | 320 |
| United States | Canada | 355 |
21 Edge
Which things in your table are connected to which? edge draws one stroke per row of the table, between the two things that row names. The other strokes draw between positions taken from columns. A line runs along its domain, a path follows the table’s order, an interval spans two values. An edge is different, because the endpoints of an edge are names, not numbers, so no axis can measure them. The picture an edge layer makes is the network diagram.
So an edge takes no x and no y. Its two endpoints come from a layout, a transform that reads the two name columns and computes a position for every name. Write the source column first and the destination second.
trade_partners holds one row per trade relation: who exports, who imports, and the value of the goods, in billions of dollars, rounded:
Name the table, then write three things: the mark, its layout, and the space network():
data(trade_partners) + edge * layout(exporter, importer) + network()data(trade_partners) + edge * layout(col.exporter, col.importer) + network()data(trade_partners) + edge * layout(:exporter, :importer) + network()plot(data(trade_partners),
layer(edge, layout(col.exporter, col.importer)), network())“Given trade partners: edges derived by layout from exporter to importer, in the network.”
An edge draws only inside network(). Every other space labels its axes with numbers, and an edge’s two endpoints are names. gog refuses the sentence rather than drawing it.
21.1 Color and opacity, one per row
Every stroke in the network above looks the same, so a trade of 500 billion looks like a trade of 50. The table holds the value, and a stroke can show it by how dark it is. An edge is one row, so its color and its opacity can follow a column of the table. color maps a category, and opacity maps a number such as billions. A second layer, point * layout(exporter, importer), reads the same layout and draws a dot at each name:
data(trade_partners) +
edge * layout(exporter, importer) + opacity(billions) +
point * layout(exporter, importer) +
network() +
title("Heavier trade, darker stroke")(data(trade_partners) +
edge * layout(col.exporter, col.importer) + opacity(col.billions) +
point * layout(col.exporter, col.importer) +
network() +
title("Heavier trade, darker stroke"))data(trade_partners) + edge * layout(:exporter, :importer) +
opacity(:billions) + point * layout(:exporter, :importer) + network() +
title("Heavier trade, darker stroke")plot(data(trade_partners),
layer(edge, layout(col.exporter, col.importer)), opacity(col.billions),
layer(point, layout(col.exporter, col.importer)), network(),
title("Heavier trade, darker stroke"))“Given trade partners: edges derived by layout from exporter to importer, opacity by billions, and also points derived by layout from exporter to importer, in the network.”
On line, opacity is only a setting, because a line is one stroke with one value. An edge layer is many strokes, and each row gives its stroke an opacity of its own.
Which strokes start at the same country? color works the same way, one value per row. Each stroke takes the color of its exporter, so Germany’s five strokes share one color:
data(trade_partners) +
edge * layout(exporter, importer) + color(exporter) +
point * layout(exporter, importer) +
network() +
title("Each stroke, colored by its exporter")(data(trade_partners) +
edge * layout(col.exporter, col.importer) + color(col.exporter) +
point * layout(col.exporter, col.importer) +
network() +
title("Each stroke, colored by its exporter"))data(trade_partners) + edge * layout(:exporter, :importer) +
color(:exporter) + point * layout(:exporter, :importer) + network() +
title("Each stroke, colored by its exporter")plot(data(trade_partners),
layer(edge, layout(col.exporter, col.importer)), color(col.exporter),
layer(point, layout(col.exporter, col.importer)), network(),
title("Each stroke, colored by its exporter"))“Given trade partners: edges derived by layout from exporter to importer, color by exporter, and also points derived by layout from exporter to importer, in the network.”
21.2 What you can set
Whether the strokes are thin or thick, solid or dashed, is not in any column of the table. A setting decides that without reading one, and each mark takes its own. These are an edge’s, generated from the engine’s own legality table, so this page cannot differ from what style() accepts:
| Setting | Value |
|---|---|
style(color = ) |
any CSS color name or hex |
style(opacity = ) |
0 to 1 |
style(size = ) |
pixels |
style(pattern = ) |
solid, dashed, dotted |
style(size = ) sets the stroke width for the whole layer. style(color = ) and style(opacity = ) give every stroke one value, for the case where no column maps. style(pattern = ) chooses the dash: solid, dashed or dotted.
The grid of every mark and every setting shows which other marks share this list. What a mark maps rather than sets is its row on the companion grid.
21.3 What it refuses
The other marks take their positions from x and y, so writing them on an edge is the natural first attempt. An edge with no layout has no endpoints to draw. x and y cannot supply them, so gog refuses each binding, then refuses the empty network():
data(trade_partners) + edge + x(billions) + y(exporter) + network()data(trade_partners) + edge + x(col.billions) + y(col.exporter) + network()data(trade_partners) + edge + x(:billions) + y(:exporter) + network()plot(data(trade_partners), edge, x(col.billions), y(col.exporter),
network())Error:
! gog: `x` cannot be bound to `edge` — an edge has no x feature. Remove the `billions` mapping from `x`, or use a mark that has one.
gog: `y` cannot be bound to `edge` — an edge has no y feature. Remove the `exporter` mapping from `y`, or use a mark that has one.
gog: `network()` draws what a `layout` places, and nothing here carries one. Compose the syllable: `edge * layout(from, to) + network()`, with `point * layout(...)` for the nodes and `text * layout(...) + label(name)` for their names.
gog: nothing was rendered. Fix the above, or set GOG_STRICT=0 to draw anyway.
A layout is read only inside network(), so the space cannot be left out:
data(trade_partners) + edge * layout(exporter, importer)data(trade_partners) + edge * layout(col.exporter, col.importer)data(trade_partners) + edge * layout(:exporter, :importer)plot(data(trade_partners),
layer(edge, layout(col.exporter, col.importer)))Error:
! gog: a `layout`'s positions are the graph's, not the data's — an axis under them would number something no reader can mean. Draw it in the network: `+ network()` flat, or `+ network(turn = 30, tilt = 25)` for the cube.
gog: nothing was rendered. Fix the above, or set GOG_STRICT=0 to draw anyway.
The Network chapter draws the rest: a dot for every name, a label beside each dot, the same graph in a cube, and the other refusals.