Outputs you create
evidence- Dataframe with
k,inertiaandsilhouettecolumns fork=2–8.
- Dataframe with
sizes- Group
sizesindexed by cluster label.
- Group
profiles- Original-unit means grouped by aligned cluster labels.
labels- One cluster label per fitted row; equivalent consistent label names are accepted.
length_mm | width_cm |
|---|---|
| 1085.48 | 12.3736 |
| 795.065 | 6.81964 |
| 302.857 | 13.4007 |
| 1005.83 | 10.7201 |
| 725.742 | 14.2927 |
| 1330.12 | 9.57362 |
| 805.448 | 8.75158 |
| 720.481 | 10.093 |
Your task
- Scale every CLUSTER36B observation
- Compare
k=2 through 8 withinertiaandsilhouette - Choose a defensible fitted grouping, and store
evidence,labels,sizesand original-unitprofiles. - Draw length against width with distinct group markers and labelled axes, then qualify the interpretation.
evidencesizesprofileslabelsHints
Think: Reconstruct discovery without importing a supervised target or a unique correct grouping.
Tools: Scaling, KMeans k comparison, silhouette, sizes and original-unit profiles.
Approach: Define the population, compare resolutions, choose a defensible grouping and report its profiles with a qualified visual.
Explained solution
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt
import seaborn as sns
X=df.copy()
scaler=StandardScaler()
scaled=scaler.fit_transform(X)
rows=[]
for k in range(2,min(8,len(X)-1)+1):
candidate=KMeans(n_clusters=k,n_init=20,random_state=42).fit(scaled)
score=silhouette_score(scaled,candidate.labels_,sample_size=min(2000,len(X)),random_state=42)
rows.append({'k':k,'inertia':candidate.inertia_,'silhouette':score})
evidence=pd.DataFrame(rows)
# Three is an illustrative choice to discuss against the evidence, not a unique optimum.
model=KMeans(n_clusters=3,n_init=20,random_state=42).fit(scaled)
labels=model.labels_
sizes=pd.Series(labels).value_counts().sort_index()
profiles=X.groupby(labels).mean()
fig,ax=plt.subplots(figsize=(6,4))
sns.scatterplot(data=X,x='length_mm',y='width_cm',hue=labels,style=labels,ax=ax)
ax.set(xlabel='Length (mm)',ylabel='Width (cm)',title='Exploratory measurement groups')
ax.legend()
fig.savefig('clusters.png',dpi=150,bbox_inches='tight')
print(evidence)
The workflow joins geometric evidence with substantive interpretation; neither the selected k nor the group IDs claim a hidden class truth.