Datalens.ai
← All algorithms

CLUSTERING

K-Medoids (PAM)

Partition observations around representative data points (medoids), rather than averaged centroids.

Example of usage

Group observations using actual observations as cluster centres.

Usage / limitations

+Use when: Choose robust, interpretable cluster representatives, especially with arbitrary distance functions.

−Limitations: Pairwise distances and swap search can be costly for large datasets; initial medoids may influence results.

Mathematical formula

minimize sum_i min_{m in medoids} d(x_i, x_m)
Sample dataShow
{
  "variable": "customers",
  "domain": "Customer engagement segmentation",
  "feature_names": [
    "monthly_spend_gbp",
    "visits_per_month"
  ],
  "records": [
    {
      "customer_id": "C01",
      "monthly_spend_gbp": 20,
      "visits_per_month": 2
    },
    {
      "customer_id": "C02",
      "monthly_spend_gbp": 22,
      "visits_per_month": 3
    },
    {
      "customer_id": "C03",
      "monthly_spend_gbp": 18,
      "visits_per_month": 2
    },
    {
      "customer_id": "C04",
      "monthly_spend_gbp": 80,
      "visits_per_month": 12
    },
    {
      "customer_id": "C05",
      "monthly_spend_gbp": 84,
      "visits_per_month": 13
    },
    {
      "customer_id": "C06",
      "monthly_spend_gbp": 78,
      "visits_per_month": 11
    }
  ]
}

Code example (Python)

# DataLens.ai example
# Domain: Customer engagement segmentation.
# The sample data above are included automatically when copied.
import numpy as np
from itertools import combinations
from math import dist

# Build the numeric feature matrix from named customer attributes.
X = np.array([[record[feature] for feature in customers["feature_names"]] for record in customers["records"]], dtype=float)

# Fit or evaluate the requested clustering technique.
# Exhaustive search illustrates the medoid objective for six observations.
points = [tuple(row) for row in X]
def objective(medoids):
    return sum(min(dist(point, points[idx]) for idx in medoids) for point in points)
medoid_indices = min(combinations(range(len(points)), 2), key=objective)
assert len(medoid_indices) == 2 and any(i < 3 for i in medoid_indices) and any(i >= 3 for i in medoid_indices)

# All checks passed; no exception was raised.
print("Expected output verified")