Skip to main content

circular_clustering

Adaptation of X means algorithm for circular data

Install the package using:

pip install circular-clustering

X means algorithm with quantiles

The class CircularXMeansQuantiles contains the X means algorithm for circular data. The use is similar to the clustering algorithms in scipy.

To import it:

from circular_clustering.circular_x_means_quantiles import CircularXMeansQuantiles

To invoke the class:

circXmeans = CircularXMeansQuantiles(x, kmax=8, confidence=0.99, use_optimal_k_means=True)
  • x must be a one-dimensional NumPy array of angles between -π and π.
  • kmax= sets the maximum number of clusters.

To fit the algorithm:

circXmeans.fit()

Centroids are available at circXmeans.centroids, and labels at circXmeans.labels.

Example (circular data):

import numpy as np
import matplotlib.pyplot as plt

from circular_clustering.circular_x_means_quantiles import CircularXMeansQuantiles

x = np.array([ 1.658,  1.369,  1.783,  1.587,  0.942,  1.268,
               1.740,  2.245,  1.955,  1.132, -1.694, -1.121,
              -1.249, -1.834, -1.868, -1.351, -1.492, -1.607,
              -1.323, -1.913,  0.099,  0.060, -0.074, -0.127,
               0.179,  0.006,  0.273, -0.285,  0.080,  0.301])

circXmeans = CircularXMeansQuantiles(x, kmax=8, confidence=0.99, use_optimal_k_means=True)
circXmeans.fit()

plt.figure(figsize=(5,5))
plt.axes().set_aspect('equal', 'datalim')
plt.scatter(np.cos(x), np.sin(x))

for c in circXmeans.centroids:
    plt.scatter(np.cos(c), np.sin(c), c="r")

for cl in circXmeans.cluster_points:
    plt.scatter(np.cos(cl), np.sin(cl), c=np.random.rand(3,))

plt.show()

result


Cylindrical clustering with HDR-based XMeans

The CylindricalXMeansHDR class supports clustering in cylindrical coordinates, where data has both an angular and linear component (θ, y). Clustering is performed using HDR-based region separation and a custom cylindrical distance metric.

To import:

from circular_clustering import CylindricalXMeansHDR

Example (cylindrical data):

import numpy as np
import matplotlib.pyplot as plt
from circular_clustering.cylindrical_hdr_x_means import CylindricalXMeansHDR

# Fix seed for reproducibility
np.random.seed(42)

# Function to create elliptical clusters on the cylinder
def make_cluster(center_theta, center_y, spread_theta, spread_y, n=100):
    theta = np.random.vonmises(center_theta, 1 / (spread_theta ** 2), size=n)
    y = np.random.normal(center_y, spread_y, size=n)
    return np.column_stack([theta, y])

# One cluster near -π, one near π, one at 0
X = np.vstack([
    make_cluster(np.pi - 0.2, 0.5, 0.15, 0.2),     # Cluster near +π
    make_cluster(-np.pi + 0.2, -0.5, 0.15, 0.2),   # Cluster near -π (should wrap!)
    make_cluster(0.0, 1.5, 0.2, 0.2),              # Central cluster
])

# Run HDR-based X-Means clustering
alpha = 0.3
xmeans = CylindricalXMeansHDR(X, kmax=6, confidence=1 - alpha, random_state=0)
xmeans.fit()
print(f"Found clusters: {xmeans.k}")

# Plot results
colors = plt.cm.tab10.colors
plt.figure(figsize=(8, 6))
for i in range(xmeans.k):
    cluster = X[xmeans.labels == i]
    plt.scatter(cluster[:, 0], cluster[:, 1], color=colors[i % 10], alpha=0.6, s=20, label=f"Cluster {i}")

plt.title(f"CylindricalXMeansHDR clustering (wraparound test)\nFound {xmeans.k} clusters")
plt.xlabel("Angle θ (radians)")
plt.ylabel("Height y")
plt.xlim(-np.pi, np.pi)
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()

result

Cylindrical data with HDR++ Merge

from circular_clustering.cylindrical_hdrpp_merge import CylindricalKMeansPPHDRMerge

# X: (n, 2) with columns (theta, z), theta in radians

# 1) Manual init with explicit centers (theta0,z0), (theta1,z1), ...
init_centers = np.array([
    [0.0,  0.0],
    [1.5,  2.0],
    [-2.2, -1.0],
])
model = CylindricalKMeansPPHDRMerge(
    X, kmax=10, confidence=0.95, init="manual", init_centers=init_centers
).fit()

# 2) Manual init from indices into X
init_indices = np.array([3, 42, 105])
model = CylindricalKMeansPPHDRMerge(
    X, kmax=10, confidence=0.95, init="manual", init_indices=init_indices
).fit()

# 3) Random init (uniformly pick up to kmax rows of X)
model = CylindricalKMeansPPHDRMerge(
    X, kmax=10, confidence=0.95, init="random", random_state=0
).fit()

# 4) Default k-means++ seeding (original behaviour)
model = CylindricalKMeansPPHDRMerge(
    X, kmax=10, confidence=0.95, random_state=0
).fit()

Metadata

Release files for circular-clustering 0.0.12

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

Source distribution (sdist)

Source distribution for circular-clustering 0.0.12
File Size Uploaded
circular_clustering-0.0.12.tar.gz 14.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for circular-clustering 0.0.12
File Interpreter ABI Platform
circular_clustering-0.0.12-py3-none-any.whl Python 3 none any Details

Total release size: 30.6 kB

Release files / circular_clustering-0.0.12.tar.gz

Download URL circular_clustering-0.0.12.tar.gz
Size 14.3 kB
Tags Source
SHA-256 checksum
How to use checksums
004cb6db2243602ce52add74bd7fd97b0562bab610935950a6541208b7ed755b
BLAKE2b-256 checksum
How to use checksums
837282aa1ac4c2db3ffc7fba31d7f753bae44ce08472cd2241d9778d2456717a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.11.2

Release files / circular_clustering-0.0.12-py3-none-any.whl

Download URL circular_clustering-0.0.12-py3-none-any.whl
Size 16.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
429997d1059afe1a57ef2d24b4e272a01e7edeb9703bb4f241018ae35dbfc0d3
BLAKE2b-256 checksum
How to use checksums
9bf0adc29682aaf0c37ff1032c320762583f1ea8de1b96c22aa39a758f9c36b2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.11.2

Release history Release notifications | RSS feed

This release

0.0.12 This release

2 release files

0.0.11

2 release files

0.0.10

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

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