kdiagram.plot.relationship.plot_relationship¶
- kdiagram.plot.relationship.plot_relationship(y_true, *y_preds, names=None, title=None, theta_offset=0.0, theta_scale='proportional', acov='default', figsize=None, cmap='tab10', s=50, alpha=0.7, legend=True, show_grid=True, grid_props=None, color_palette=None, xlabel=None, ylabel=None, z_values=None, z_label=None, savefig=None, ax=None)[source]¶
Visualize the relationship between true values and one or more prediction series on a polar (circular) scatter plot.
Each point uses an angular position derived from
y_trueand a radial position derived from the corresponding prediction. This compact view lets you compare multiple prediction series against the same truth—useful for spotting systematic deviations and patterns over a cyclic or ordered domain (e.g., phase, time-of-year).- Parameters:
- y_truearray_like
ofshape(n_samples,) Ground-truth (observed) values. Must be numeric, 1D, and the same length as every array in
y_preds.- *y_predsarray_like(
s) One or more prediction arrays, each with shape
(n_samples,)and aligned toy_true.- names
listofstr,optional Labels for each prediction series. If fewer names than series are provided, placeholders like
'Model_3'are appended.- title
str,optional Figure title. If
None, uses'Relationship Visualization'.- theta_offset
float, default=0 Constant angular shift (radians) applied after the angle mapping.
- theta_scale{‘proportional’, ‘uniform’}, default=’proportional’
Strategy for mapping
y_trueto angles:'proportional': angle proportional to the scaled value ofy_truewithin its range over the selected angular span.'uniform': angles evenly spaced over the selected span, ignoring the numerical spacing iny_true.
- acov{‘default’, ‘half_circle’, ‘quarter_circle’, ‘eighth_circle’},
default=’default’ Angular coverage (span) of the plot:
'default': \(2\pi\) (full circle)'half_circle': \(\pi\)'quarter_circle': \(\tfrac{\pi}{2}\)'eighth_circle': \(\tfrac{\pi}{4}\)
- figsize
tupleof(float,float),optional Figure size in inches. If
None, a sensible default is used.- cmap
str, default=’tab10’ Matplotlib colormap name used to generate distinct series colors.
- s
float, default=50 Marker size for scatter points.
- alpha
float, default=0.7 Alpha (transparency) for scatter points in
[0, 1].- legendbool, default=True
If
True, show a legend for the prediction series.- show_gridbool, default=True
Toggle polar grid lines (delegated to
set_axis_grid).- grid_props
dict,optional Keyword arguments forwarded to the grid helper (e.g.,
linestyle,alpha).- color_palette
listofcolor-like,optional Explicit list of colors. If omitted, colors are derived from
cmap. If provided with fewer colors than series, they repeat.- xlabel
str,optional Label for the radial axis. Defaults to
'Normalized Predictions (r)'.- ylabel
str,optional Label for the angular axis. Defaults to
'Angular Mapping (θ)'whenz_valuesis not used.- z_valuesarray_like
ofshape(n_samples,),optional Optional values used to label angular ticks (e.g., time, phase). If provided, a subset of positions is selected and tick labels are replaced by formatted entries from
z_values.- z_label
str,optional Axis/legend label describing
z_values(shown as text next to the angular tick labels region).- savefig
str,optional Path to save the figure (with extension). If
None, the figure is shown instead.
- y_truearray_like
- Returns:
- ax
matplotlib.axes.Axes The polar axes containing the visualization.
- ax
- Parameters:
See also
kdiagram.plot.uncertainty.plot_temporal_uncertaintyGeneral polar series visualization (e.g., quantiles).
kdiagram.plot.uncertainty.plot_actual_vs_predictedSide-by-side truth vs. point prediction comparison.
Notes
Angular span. Let \(\Delta\theta\) be the selected span: \(2\pi\) (full), \(\pi\), \(\pi/2\), or \(\pi/4\) depending on
acov. Angles are then limited to \([0,\,\Delta\theta]\) and shifted bytheta_offset.Angle mapping. For \(N=\text{len}(y_{\text{true}})\) and \(i=0,\dots,N-1\):
Proportional mapping (range-aware):
(1)¶\[\begin{split}\theta_i \;=\; \begin{cases} \dfrac{y_i - y_{\min}}{y_{\max}-y_{\min}}\,\Delta\theta, & \text{if } y_{\max}>y_{\min},\\[6pt] 0, & \text{otherwise,} \end{cases}\end{split}\]where \(y_{\min}=\min_i y_i\) and \(y_{\max}=\max_i y_i\).
Uniform mapping (index-based):
(2)¶\[\theta_i \;=\; \frac{i}{N}\,\Delta\theta.\]
Radial normalization. Each prediction series \(p\) is scaled to \([0,1]\) by
(3)¶\[\begin{split}r_i \;=\; \begin{cases} \dfrac{p_i - p_{\min}}{p_{\max}-p_{\min}}, & p_{\max}>p_{\min},\\[6pt] 0.5, & \text{otherwise,} \end{cases}\end{split}\]to give comparable radii across heterogeneous series [1].
Data preparation. The function first removes joint NaNs via
drop_nan_inand validates each pair(y_true, y_pred)throughvalidate_yy(continuous expectations, 1D arrays). Colors are drawn fromcmapunlesscolor_paletteis supplied. Grid appearance is managed byset_axis_grid.Interpretation. When
theta_scale='proportional', nearby angles reflect similar truth values; with'uniform', angles reflect order only. Clustering by color (series) indicates systematic agreement or disagreement versus truth across the domain [2].References
Examples
Basic comparison over a full circle:
>>> import numpy as np >>> from kdiagram.plot.relationship import plot_relationship >>> rng = np.random.default_rng(0) >>> y = rng.random(200) >>> p1 = y + rng.normal(0, 0.10, size=len(y)) >>> p2 = y + rng.normal(0, 0.20, size=len(y)) >>> ax = plot_relationship( ... y, p1, p2, ... names=["Model A", "Model B"], ... acov="default", ... title="Truth–Prediction (Full Circle)" ... )
Half-circle with custom angular tick labels (e.g., months):
>>> months = np.linspace(1, 12, len(y)) >>> ax = plot_relationship( ... y, p1, ... names=["Model A"], ... theta_scale="uniform", ... acov="half_circle", ... z_values=months, ... z_label="Month", ... xlabel="Normalized Predictions (r)" ... )