Skip to main content

pytrendclust

PyPI Python License: MIT

Source code: https://github.com/89605502155/pytrendclust

Trend clustering of time series with an adaptive number of clusters.

pytrendclust splits a series into consecutive runs that rise, fall or stay flat. You do not pass the number of clusters. It is chosen by a penalised least-squares criterion in which every extra change point costs exponentially more than the previous one. Real changes of direction are found, and noise is not mistaken for a trend.

Typical use: keep only the most recent regime of a series as the training set for a regression model. For example, a series of RAM consumption first falls and then grows. Fitting a line to the whole history mixes two regimes; fitting it to the last cluster does not.

from pytrendclust import TrendClusterer

y = [10, 9, 8, 7, 6, 5, 4, 5, 6, 7]

result = TrendClusterer().fit(y).result_
print(result.summary())
# 10 points, 1 change point(s), noise std 0.27
#   #0: [0, 7)    7 pts  down  slope -1
#   #1: [7, 10)    3 pts  up    slope +1

t_recent, y_recent = result.select()       # points of the last (newest) cluster
result.export("result.json")               # or "points.csv"

A "picket fence" 5, 6, 5, 6, ... is one flat cluster, not ten tiny trends:

>>> from pytrendclust import cluster_trends
>>> cluster_trends([5, 6] * 5).summary()
'10 points, 0 change point(s), noise std 1.211\n  #0: [0, 10)   10 pts  flat  slope +0.0303'
>>> cluster_trends([5, 6] * 5, penalty="none").n_change_points   # no regularisation
2

Installation

pip install pytrendclust            # numpy only
pip install "pytrendclust[pandas]"  # + DataFrame export

Method

For every possible number of change points K, a dynamic programme finds the exact partition into K + 1 runs with the smallest total squared error of per-run least-squares lines, SSE(K). The clusterer then picks

K* = argmin_K  SSE(K) + sigma² · pen(K)
pen(K) = c · (exp(g·K) − 1) / (exp(g) − 1)
  • c (penalty_scale): price of the first change point in noise variances. The default is 5·ln(n).
  • g (penalty_growth, default 0.5): each next change point costs e^g times more than the previous one. g = 0 gives the classic linear penalty.
  • sigma (noise_std): noise level. By default it is estimated robustly from second differences of the series, which cancel any linear trend. This makes the result independent of units: bytes and gigabytes give the same clusters.

The search over K stops as soon as the penalty alone exceeds the best value found. The exponential penalty makes this happen after a few steps. The solution is the global optimum of the criterion; the test suite checks it against brute-force enumeration.

Each cluster is labelled up, down or flat with a t-test on its slope: |slope| / se(slope) < flat_threshold (default 2) means flat.

API

Object Purpose
TrendClusterer(**params) set parameters; fit(y, t=None), fit_predict, get_params, set_params
cluster_trends(y, t=None, **params) one-call shortcut returning the result
TrendClusteringResult segments, change_points, labels, trends, fitted, last_segment, select(), indices(), criterion
export to_dict(), to_json(path), to_csv(path), to_dataframe(), export(path); from_dict, from_json

Parameters: penalty ("exponential", "linear", "none", or a callable f(K, n, sigma²)), penalty_scale, penalty_growth, min_size (default 3), max_change_points, noise_std, flat_threshold.

result.criterion lists SSE(K), the penalty and their sum for every K the search evaluated. Use it to justify the chosen number of clusters.

Complexity is O(K · n²) time and O(K · n) memory: about 0.4 s for 1000 points and 6 s for 5000.

Кратко по-русски

Трендовая кластеризация временного ряда с адаптивным числом классов. Ряд делится на участки роста, спада и плато. Число точек разладки выбирается автоматически: к ошибке модели добавляется штраф, растущий экспоненциально с каждой новой точкой. Так шумовые колебания («заборчик») не принимаются за смену тренда. result.select() возвращает точки последнего, самого свежего участка. На них обучается регрессия.

Development

git clone https://github.com/89605502155/pytrendclust.git
cd pytrendclust
uv sync --all-extras
uv run pytest
uv run ruff check src tests && uv run ruff format --check src tests
uv run mypy
uv build

License

MIT, see LICENSE.

Metadata

Release files for pytrendclust 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytrendclust 0.1.0
File Size Uploaded
pytrendclust-0.1.0.tar.gz 14.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytrendclust 0.1.0
File Interpreter ABI Platform
pytrendclust-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 31.9 kB

Release files / pytrendclust-0.1.0.tar.gz

Download URL pytrendclust-0.1.0.tar.gz
Size 14.6 kB
Tags Source
SHA-256 checksum
How to use checksums
0db06be9dc62b5d1adbe6fc3f85c9fecddead33d1031c946ac641cd569bc6828
BLAKE2b-256 checksum
How to use checksums
5c267f6fb5f80a544a9c2c9e6fc48b8b3a0cde93ef8009ef0311d18a5157cc0a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.9 {"installer":{"name":"uv","version":"0.11.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / pytrendclust-0.1.0-py3-none-any.whl

Download URL pytrendclust-0.1.0-py3-none-any.whl
Size 17.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7252aad11f0eaa30e1277bf052f04eda85e42192c18b8a9abe31407f3a4de29c
BLAKE2b-256 checksum
How to use checksums
9493ed17641c04398349efc7780ced38211129df286bc11a2de910ebf0738b8f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.9 {"installer":{"name":"uv","version":"0.11.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page