An anomaly is an observation that stands out from what is usual. In a time series, an extreme value is a particularly simple case: a reading unusually high or low relative to the series. The judgment depends on context. A flagged point is not automatically an error or a finding of interest; it is a reason to investigate. section 17.2.1 section 1.4
For a series with a fairly constant level and variability, set lower and upper limits and flag values outside them. One approach uses the first and third quartiles, Q1 and Q3, and the interquartile range, IQR = Q3 − Q1. The sales example sets its limits at Q1 − 2.2 × IQR and Q3 + 2.2 × IQR. IQR is more robust to outliers than limits based on the mean and standard deviation, but the multiplier still needs tuning to balance missed anomalies against excessive flags. Clear rules are useful when they can be formulated: they run efficiently and are interpretable. section 17.2.1
An unusually high sales day
A single unusual daily sales count is added to a January series. Its value falls beyond limits calculated from the full year, making it straightforward to flag even though the plot displays only January. In industrial sensor data, unusual readings can instead prompt investigation of equipment or help plan maintenance; detection identifies a deviation, not an imminent failure. section 17.2.1 section 1.1.5
Fixed limits are not the only perspective. Time-series anomalies can also be departures from a forecast, changes in a series, unusual shapes, or deviations from the usual relationship between series. Where a series is better assessed against changing expectations, a forecasting tool such as Prophet can supply predicted values and confidence ranges; observations outside a range can then be investigated. Forecasting many steps ahead widens those ranges, so the prediction setup matters. Whatever the detector, examine flagged results to determine what is unusual and whether it matters. section 17.4 section 17.3.3 section 15.2
Listing 17.2 Identifying extreme values in sales data
daily_median = sales_days_df['Count'].median() #1
q1 = sales_days_df['Count'].quantile(0.25)
q3 = sales_days_df['Count'].quantile(0.75)
iqr = q3 - q1
lower_limit = q1 - 2.2*iqr
upper_limit = q3 + 2.2*iqr
jan_sales_df = sales_days_df[:31].copy()
jan_sales_df.loc['2023-01-15'] = 4033 #2
flagged_vals = [] #3
for i in jan_sales_df.index:
v = jan_sales_df.loc[i]['Count']
if v < lower_limit or v > upper_limit:
flagged_vals.append((i, v))
fig, ax = plt.subplots(figsize=(15, 2.5)) #4
ax.axhline(lower_limit) #5
ax.axhline(daily_median)
ax.axhline(upper_limit)
ax.fill_between(jan_sales_df.index, lower_limit, upper_limit, alpha=0.1)
sns.lineplot(data=jan_sales_df)
sns.scatterplot(x=[x[0] for x in flagged_vals],
y=[x[1] for x in flagged_vals], marker='*', s=500)
plt.show()
Python example calculating IQR-based limits, flagging daily sales counts outside them, and plotting the expected region. section 17.2.1













