# Experiment 7: K-Means Clustering for Customer Profiling
# Requirements: pip install numpy pandas matplotlib seaborn scikit-learn

# ==========================================
# STEP 1: Import Libraries & Load Dataset
# ==========================================
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score

# Load Dataset
# CHANGE THIS PATH TO YOUR DATASET (Mall_Customers.csv)
df = pd.read_csv('Mall_Customers.csv')

print("--- Dataset Head ---")
print(df.head())
print("\n--- Dataset Info ---")
print(df.info())

# Select relevant numerical features
X = df[['Annual Income (k$)', 'Spending Score (1-100)']].values

# STEP 2: Feature Scaling
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# STEP 3: Find Optimal K
wcss = []
silhouette_scores = []
K_range = range(2, 11)

for k in K_range:
    kmeans = KMeans(n_clusters=k, init='k-means++',
                    random_state=42, n_init=10)
    kmeans.fit(X_scaled)
    wcss.append(kmeans.inertia_)
    silhouette_scores.append(
        silhouette_score(X_scaled, kmeans.labels_)
    )

plt.figure(figsize=(12, 5))

plt.subplot(1, 2, 1)
plt.plot(range(2, 11), wcss, marker='o', color='b')
plt.title('Elbow Method for Optimal K')
plt.xlabel('Number of Clusters (K)')
plt.ylabel('WCSS (Inertia)')
plt.grid(True)

plt.subplot(1, 2, 2)
plt.plot(range(2, 11), silhouette_scores, marker='s', color='g')
plt.title('Silhouette Score Analysis')
plt.xlabel('Number of Clusters (K)')
plt.ylabel('Silhouette Score')
plt.grid(True)

plt.tight_layout()
plt.show()

# STEP 4: Train K-Means with Optimal K
optimal_k = 5
kmeans = KMeans(n_clusters=optimal_k, init='k-means++',
                random_state=42, n_init=10)
y_kmeans = kmeans.fit_predict(X_scaled)
df['Cluster'] = y_kmeans

# STEP 5: Visualize Customer Profiles
plt.figure(figsize=(9, 6))
colors = ['red', 'blue', 'green', 'cyan', 'magenta']
labels = ['Cluster 1', 'Cluster 2', 'Cluster 3', 'Cluster 4', 'Cluster 5']

for i in range(optimal_k):
    plt.scatter(X_scaled[y_kmeans == i, 0],
                X_scaled[y_kmeans == i, 1],
                s=50, c=colors[i], label=labels[i])

plt.scatter(kmeans.cluster_centers_[:, 0],
            kmeans.cluster_centers_[:, 1],
            s=200, c='yellow', edgecolors='black',
            marker='*', label='Centroids')

plt.title('Customer Segments (K-Means Clustering)')
plt.xlabel('Annual Income (Scaled)')
plt.ylabel('Spending Score (Scaled)')
plt.legend()
plt.grid(True)
plt.show()

# Display summary metrics per cluster
profile = df.groupby('Cluster')[
    ['Annual Income (k$)', 'Spending Score (1-100)', 'Age']
].mean()
print(profile)
