sp.joint() composes a bivariate main panel with top and right marginal strips — the SeraPlot equivalent of seaborn's jointplot() / JointGrid. variant= (the panel, "inside") and marginal= (the top/right strips, "outside") are independent, fully open choices — not a fixed enum. Each accepts the name of any registered SeraPlot family from services/plot/statistical/chart_registry.rs (currently ~50: hexbin, scatter, kde, histogram, bar, violin, boxplot, heatmap, orbita, splom, … the same inventory facet() dispatches through), and panel_variant= / marginal_variant= forward straight through as that family's own variant=, so hexbin's outlined/spaced/highlight styles, histogram's cumulative, etc. all work exactly as they do standalone.
sp.joint(x, y, variant="hexbin", marginal="kde")
sp.joint(x, y, variant="kde", marginal="histogram")
sp.joint(x, y, variant="scatter", marginal="bar")
sp.joint(x, y, variant="hexbin", panel_variant="outlined", marginal="kde")
Each region — panel, top strip, right strip — is a real, independently-rendered SeraPlot chart embedded in its own frame, calling the exact same native build_* function facet() uses for its cells; nothing is reimplemented. That also means regions are not pixel-aligned to a shared coordinate system the way a hand-tuned single-SVG composition would be — each chart keeps its own axes/padding — an inherent tradeoff for genuine "any family, any slot" freedom. Not every family produces something meaningful in every slot — that limitation belongs to the target family's own data shape, not to joint() itself. As a marginal, a family only ever receives the single axis of values being summarized (plus generic synthetic labels/categories/series/sizes/words so families expecting those shapes still degrade gracefully); families whose own data model is inherently 2D/matrix/hierarchical/paired — candlestick, chord, circle_pack, correlogram, dendrogram, dumbbell, gantt, hive, heatmap, icicle, orbita, parcats, radar, sankey, scatterternary, slope, splom, sunburst — render blank there, the same honest way orbita renders blank as a panel without a hierarchy.
For a true bivariate (2D) density surface — not just kde's own 1D curve — use variant="kde", panel_variant="contour": kde()'s contour variant fits a product-kernel Gaussian KDE jointly over x and y and shades a smooth density surface with the raw points overlaid, matching seaborn's smooth_bivariate_kde / joint_kde examples. Legacy preset names (layered_bivariate, joint_kde, kde_smooth, smooth_bivariate_kde, …) already resolve to exactly this.
The preset names from earlier releases (hexbin_marginal, joint_histogram / histogram2d, layered_bivariate, joint_kde, kde_smooth, multiple_bivariate_kde, marginal_ticks, regression_marginals) still work as variant= values and resolve to a real family under the hood (resolve_legacy_panel() in joint/variant.rs), so existing code keeps working. heat_scatter — seaborn's correlation matrix drawn as sized/colored scatter dots — isn't a joint/marginal plot at all; use heatmap(variant="bubble") directly.
Chart — object with .html property and .show() method.
The raw entry point — variant= is simply the panel family's own name, and any registered family can fill it.
Callsp.joint(x, y, variant="hexbin", marginal="histogram")
Preview
Hexagonal density panel with KDE curve marginals instead of the default histograms.
Callsp.joint(x, y, variant="hexbin", marginal="kde")
Preview
A 1D KDE panel with histogram marginals — mixing families freely, not just bivariate-native ones.
Callsp.joint(x, y, variant="kde", marginal="histogram")
Preview
Scatter panel with bar-chart marginals.
Callsp.joint(x, y, variant="scatter", marginal="bar")
Preview
panel_variant= forwards to the panel family's own variant — here hexbin's outlined cell style, combined with KDE marginals.
Callsp.joint(x, y, variant="hexbin", panel_variant="outlined", marginal="kde")
Preview
The pre-existing layered_bivariate preset name still resolves (to variant="kde", panel_variant="contour" under the hood — a genuine bivariate density surface, not a flat 1D curve) — old code keeps working, and now renders correctly.
sp.joint() compose un panneau bivarié principal avec des bandes marginales en haut et à droite — l'équivalent SeraPlot de jointplot() / JointGrid de seaborn. variant= (le panneau, « intérieur ») et marginal= (les bandes haut/droite, « extérieur ») sont des choix indépendants et totalement ouverts — pas une énumération figée. Chacun accepte le nom de n'importe quelle famille SeraPlot enregistrée dans services/plot/statistical/chart_registry.rs (environ 50 actuellement : hexbin, scatter, kde, histogram, bar, violin, boxplot, heatmap, orbita, splom, … le même inventaire que celui utilisé par facet()), et panel_variant= / marginal_variant= sont transmis tels quels comme le variant= propre à cette famille.
sp.joint(x, y, variant="hexbin", marginal="kde")
sp.joint(x, y, variant="kde", marginal="histogram")
sp.joint(x, y, variant="scatter", marginal="bar")
sp.joint(x, y, variant="hexbin", panel_variant="outlined", marginal="kde")
Chaque région — panneau, bande haute, bande droite — est un vrai graphique SeraPlot rendu indépendamment dans son propre cadre, appelant exactement la même fonction build_* native que facet() pour ses cellules ; rien n'est réimplémenté. Cela signifie aussi que les régions ne sont pas alignées pixel par pixel sur un système de coordonnées partagé comme le serait une composition SVG unique ajustée à la main — chaque graphique garde ses propres axes/marges — une contrepartie inhérente à une liberté « n'importe quelle famille, n'importe quel emplacement » authentique. Toutes les familles ne produisent pas quelque chose de pertinent dans tous les emplacements — cette limite appartient à la forme de données propre à la famille cible, pas à joint() lui-même. En tant que marginale, une famille ne reçoit que l'axe unique de valeurs résumé (plus des labels/categories/series/sizes/words génériques synthétisés pour que les familles attendant ces formes se dégradent tout de même proprement) ; les familles dont le modèle de données est intrinsèquement 2D/matriciel/hiérarchique/apparié — candlestick, chord, circle_pack, correlogram, dendrogram, dumbbell, gantt, hive, heatmap, icicle, orbita, parcats, radar, sankey, scatterternary, slope, splom, sunburst — restent vides dans cet emplacement, de la même façon honnête qu'orbita reste vide en tant que panneau sans hiérarchie.
Pour une véritable surface de densité bivariée (2D) — pas seulement la courbe 1D propre à kde — utilisez variant="kde", panel_variant="contour" : la variante contour de kde() ajuste une estimation par noyau gaussien (produit de noyaux) conjointement sur x et y et affiche une surface de densité lissée avec les points bruts superposés, à l'image des exemples seaborn smooth_bivariate_kde / joint_kde. Les noms hérités (layered_bivariate, joint_kde, kde_smooth, smooth_bivariate_kde, …) se résolvent déjà exactement ainsi.
Les noms préréglés des versions précédentes (hexbin_marginal, joint_histogram / histogram2d, layered_bivariate, joint_kde, kde_smooth, multiple_bivariate_kde, marginal_ticks, regression_marginals) fonctionnent toujours comme valeurs de variant= et se résolvent vers une vraie famille en interne (resolve_legacy_panel() dans joint/variant.rs), donc le code existant continue de fonctionner. heat_scatter — la matrice de corrélation de seaborn tracée en points dimensionnés/colorés — n'est pas un graphique joint/marginal du tout ; utilisez directement heatmap(variant="bubble").
Chart — objet avec une propriété .html et une méthode .show().
Le point d'entrée brut — variant= est simplement le nom de la famille du panneau, et n'importe quelle famille enregistrée peut le remplir.
Appelsp.joint(x, y, variant="hexbin", marginal="histogram")
Aperçu
Panneau de densité hexagonale avec des marges en courbes de KDE plutôt qu'en histogrammes par défaut.
Appelsp.joint(x, y, variant="hexbin", marginal="kde")
Aperçu
Un panneau de KDE 1D avec des marges en histogrammes — mélange libre de familles, pas seulement celles nativement bivariées.
Appelsp.joint(x, y, variant="kde", marginal="histogram")
Aperçu
Panneau en nuage de points avec des marges en bar chart.
Appelsp.joint(x, y, variant="scatter", marginal="bar")
Aperçu
panel_variant= est transmis à la variante propre de la famille du panneau — ici le style de cellule outlined de hexbin, combiné à des marges KDE.
Appelsp.joint(x, y, variant="hexbin", panel_variant="outlined", marginal="kde")
Aperçu
L'ancien nom préréglé layered_bivariate se résout toujours (vers variant="kde", panel_variant="contour" en interne — une véritable surface de densité bivariée, pas une simple courbe 1D) — le code existant continue de fonctionner, et s'affiche désormais correctement.