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 — sample data: customer engagement cohorts
customers = {'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}]}
# 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")
# 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")