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