Layout#

Multi-panel grid#

Use gufo.grid() to build a fixed rows x cols layout. It returns a Grid — a dedicated layout container for multiple charts.

import gufo

g = gufo.grid(rows=2, cols=2, figsize=(14, 10))

g[0, 0] = gufo.chart(df).scatter("x", "y").title("Panel A")
g[0, 1] = gufo.chart(df).line("year", "revenue").title("Panel B")
g[1, 0] = gufo.chart(df).histogram("income").title("Panel C")
g[1, 1] = gufo.chart(df2).bar("region", "sales").title("Panel D")

g.show()

Each panel is a normal Chart built the usual way with gufo.chart(data). Assign it to a grid cell with g[row, col] = .... All Chart methods (marks, labels, themes, axis control) work on panels exactly as they do on standalone charts.

Grid-level options#

# Add a super-title above all panels
g = gufo.grid(2, 2).title("Dashboard")

# Different data per panel
g[0, 0] = gufo.chart(sales_df).scatter("x", "y")
g[0, 1] = gufo.chart(weather_df).line("date", "temp")

Saving a grid#

g.save("dashboard.png", dpi=300)
g.save("report.pdf")

Empty cells#

Any cell you don’t assign is automatically hidden. You don’t need to fill every cell.

g = gufo.grid(2, 2)
g[0, 0] = gufo.chart(df).scatter("x", "y")
# Other 3 cells stay blank
g.save("sparse.png")

Faceting#

Faceting creates one panel per value of a categorical column automatically.

# Split into one subplot per continent
gufo.chart(df).scatter("gdp", "life_exp").facet("continent").show()

# Control the number of columns before wrapping
gufo.chart(df).scatter("gdp", "life_exp").facet("continent", cols=4).show()

Two-variable faceting#

Use row to add a second dimension. Row categories go down, column categories go across.

# Row by income group, column by continent
gufo.chart(df).scatter("gdp", "life_exp").facet("continent", row="income_group").show()

# Row only — one panel per category, stacked vertically
gufo.chart(df).scatter("gdp", "life_exp").facet(row="income_group").show()

Chart-level .title() becomes a super-title above all panels. Empty cells are hidden automatically.

Shared / independent axes#

By default, facet panels share axis ranges. Set sharex=False or sharey=False to let each panel scale independently — useful when groups have very different ranges.

gufo.chart(df).scatter("x", "y").facet("group", sharey=False).show()

Shared colorbar and legend#

When a faceted chart uses continuous color (a numeric column as color= on scatter or line), a single figure-level colorbar is drawn using the global data range across all panels, so colors are directly comparable. When .legend() is called on a faceted chart, a single figure-level legend is drawn (deduped by label) instead of one per panel.

Joint plot#

gufo.jointplot() creates a scatter plot with marginal distributions (histograms or KDE) on the top and right edges. It returns a Grid.

gufo.jointplot(df, "x", "y").show()

# KDE marginals
gufo.jointplot(df, "x", "y", marginal="kde").show()

# Color by category
gufo.jointplot(df, "x", "y", color="species").show()

Pair plot#

gufo.pairplot() generates an N×N grid of scatter plots and histograms for all numeric columns. It returns a Grid, so all grid methods work.

gufo.pairplot(df).show()
gufo.pairplot(df, color="species").title("Iris Dataset").save("pairs.png")

See Pair plot for full details.

API reference#

See gufo.layout.grid.Grid — specifically .__setitem__, .title(), .theme(), .apply(), .show(), .save().