join
One-to-many equi-join of the incoming rows against another data table on a shared key. For each incoming (left) row, every right row whose on value matches contributes one output row of the merged columns ({**left, **right}); incoming rows with no match drop out. It's the relational join you know from other tools:
| Language | Equivalent |
|---|---|
| SQL | JOIN right USING (on) |
| pandas / polars | left.merge(right, on=...) |
| dplyr (R) | left_join(right, by = on) |
Unlike resolve — which dereferences columns into the drawn nodes of a prior layer — join relates two plain data tables, so the right table is inlined into the chart's IR and round-trips as JSON.
Pie glyphs from a normalized join
A scatter of lakes by location, where each glyph inherits its lake row and joins in that lake's catch rows to draw a polar pie — two normalized tables instead of one denormalized array:
The nested glyph chart leaves off its data, so it inherits its parent partition (the lake's row) and joins the catch table onto it:
from gofish import chart, scatter, join, stack, rect, clock
chart(catch_locations).flow(scatter(by="lake", x="x", y="y")).mark(
chart(coord=clock()) # no data -> inherits this lake's partition
.flow(join(seafood, on="lake"), stack(by="species", dir="x", h=20))
.mark(rect(w="count", fill="species"))
).render(w=400, h=400)Signature
join(right, *, on) -> OperatorParameters
| Parameter | Type | Description |
|---|---|---|
right | list[dict] / DataFrame | The right-hand table — row dicts or a pandas DataFrame. |
on | str | The shared key field matched between the incoming rows and right. |
A pandas DataFrame is converted to records automatically. Returns an Operator for use inside .flow().
Semantics
- One-to-many — each incoming row fans out to one output row per matching
rightrow. A left row matching three right rows yields three output rows. - Inner match — incoming rows with no matching
rightrow drop out (there is no left-outer "keep unmatched with nulls" mode). - Column merge — output rows are
{**left, **right}; on a column-name clash therightvalue wins. - Inlined right table —
righttravels in the IR as JSON, so a chart usingjoinserializes and round-trips without a bridge (contrastderive, whose function body cannot serialize).
join vs. resolve
Both relate two tables on a key, but at different stages:
