Source code for gufo.stats.lowess

"""LOWESS smoothing overlay for scatter plots."""

from dataclasses import dataclass
from typing import Optional

import numpy as np

try:
    from statsmodels.nonparametric.smoothers_lowess import lowess as sm_lowess
except ImportError:
    sm_lowess = None


[docs] @dataclass class Lowess: """Configuration for a LOWESS smoothing curve overlaid on a scatter plot. Users create instances via gufo.lowess(), never directly. """ frac: float = 0.6667 color: Optional[str] = None linestyle: str = "-" linewidth: float = 2.0 label: Optional[str] = None
[docs] def render(self, x, y, axes): """Fit and draw the LOWESS curve on the given axes. Parameters ---------- x : numpy array — already resolved via DataAdapter. y : numpy array — already resolved via DataAdapter. axes : matplotlib Axes. """ if sm_lowess is None: raise ImportError( "LOWESS smoothing requires statsmodels. " "Install it with: pip install gufo[stats]" ) mask = np.isfinite(x) & np.isfinite(y) x_clean, y_clean = x[mask], y[mask] if len(x_clean) < 3: return result = sm_lowess(y_clean, x_clean, frac=self.frac, return_sorted=True) x_fit, y_fit = result[:, 0], result[:, 1] kwargs = { "linestyle": self.linestyle, "linewidth": self.linewidth, } if self.color is not None: kwargs["color"] = self.color if self.label is not None: kwargs["label"] = self.label axes.plot(x_fit, y_fit, **kwargs)