median_absolute_deviation(wide_residuals_df, window_width)

Compute rolling median absolute deviation (MAD) for each column (excluding first). Return a DataFrame with date and rolling MAD values.

Source code in anomaly/util.py
def median_absolute_deviation(
    wide_residuals_df: pd.DataFrame, window_width: int
) -> pd.DataFrame:
    """
    Compute rolling median absolute deviation (MAD) for each column (excluding
    first).
    Return a DataFrame with date and rolling MAD values.

    """

    # Define MAD function
    def mad(x):
        return np.median(np.abs(x - np.median(x)))

    # Apply rolling MAD
    wide_residuals_mad = wide_residuals_df.rolling(window=window_width).apply(
        mad
    )  # [2222 rows x 135 columns]
    wide_residuals_mad = wide_residuals_mad.iloc[window_width - 1 :]
    # [2180 rows x 135 columns]
    return wide_residuals_mad

median_error(wide_residuals_df, window_width)

Compute rolling median of residuals over a specified window.

Return a DataFrame with date and rolling median values, dropping initial NaN rows.

Source code in anomaly/util.py
def median_error(
    wide_residuals_df: pd.DataFrame, window_width: int
) -> pd.DataFrame:
    """Compute rolling median of residuals over a specified window.

    Return a DataFrame with date and rolling median values, dropping initial
    NaN rows.

    """
    # This will ideally use the same window.width as the PCA calculation. ???
    wide_residuals_median = wide_residuals_df.rolling(
        window=window_width
    ).median()
    # Drop the first (window_width - 1) rows
    wide_residuals_median = wide_residuals_median.iloc[window_width - 1 :]
    return wide_residuals_median

str_wrap(text, width=12)

Simulate R's str_wrap for label formatting.

Source code in anomaly/util.py
def str_wrap(text: list[str], width: int = 12):
    """Simulate R's str_wrap for label formatting."""
    if isinstance(text, str):
        words = text.split()
        lines = []
        line = ""
        for word in words:
            if len(line + " " + word) <= width:
                line += " " + word if line else word
            else:
                if line:
                    lines.append(line)
                line = word
        if line:
            lines.append(line)
        return "\n".join(lines)
    return text