Complete Exploratory Data Analysis — every step documented with findings and code.
The first thing we check is the number of rows (customers) and columns (features). This tells us the scale of the dataset and helps decide if we need sampling.
List all column names to understand what data is available before analysis.
Verifying data types ensures that numeric columns aren't stored as strings and that categorical columns are correctly typed.
| Column | Type | Sample Value |
|---|---|---|
| Gender | str | Male |
| Age | int64 | 19 |
| Annual_Income | int64 | 15 |
| Spending_Score | int64 | 39 |
| Gender_Encoded | int64 | 1 |
Missing values can cause K-Means to fail or produce incorrect clusters. We check each column for nulls before proceeding.
| Column | Missing | % | Status |
|---|---|---|---|
| Gender | 0 | 0.0% | ✅ Clean |
| Age | 0 | 0.0% | ✅ Clean |
| Annual_Income | 0 | 0.0% | ✅ Clean |
| Spending_Score | 0 | 0.0% | ✅ Clean |
| Gender_Encoded | 0 | 0.0% | ✅ Clean |
Duplicate rows skew clustering results by creating artificial density in certain regions of the feature space.
df.describe() gives count, mean, std, min/max, and quartiles for each numeric column.
| Feature | Count | Mean | Std | Min | 25% | 50% | 75% | Max |
|---|---|---|---|---|---|---|---|---|
| Age | 200 | 38.85 | 13.97 | 18.0 | 28.75 | 36.0 | 49.0 | 70.0 |
| Annual_Income | 200 | 60.56 | 26.26 | 15.0 | 41.5 | 61.5 | 78.0 | 137.0 |
| Spending_Score | 200 | 50.2 | 25.82 | 1.0 | 34.75 | 50.0 | 73.0 | 99.0 |
| Gender_Encoded | 200 | 0.44 | 0.5 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 |
The Inter-Quartile Range (IQR) method detects outliers: values below Q1−1.5×IQR or above Q3+1.5×IQR.
| Feature | Q1 | Q3 | IQR | Lower Fence | Upper Fence | Outliers |
|---|---|---|---|---|---|---|
| Age | 28.75 | 49.0 | 20.25 | -1.62 | 79.38 | 0 |
| Annual_Income | 41.5 | 78.0 | 36.5 | -13.25 | 132.75 | 2 |
| Spending_Score | 34.75 | 73.0 | 38.25 | -22.62 | 130.38 | 0 |
| Feature | Min | Max | Mean | Median | Std |
|---|---|---|---|---|---|
| Age | 18.0 | 70.0 | 38.85 | 36.0 | 13.97 |
| Annual_Income | 15.0 | 137.0 | 60.56 | 61.5 | 26.26 |
| Spending_Score | 1.0 | 99.0 | 50.2 | 50.0 | 25.82 |
| Gender_Encoded | 0.0 | 1.0 | 0.44 | 0.0 | 0.5 |
Pearson correlation measures linear relationships (−1 to +1). Values near 0 indicate independent features — good for K-Means as we want feature diversity.
| Feature | Age | Annual_Income | Spending_Score | Gender_Encoded |
|---|---|---|---|---|
| Age | 1.0 | -0.012 | -0.327 | 0.061 |
| Annual_Income | -0.012 | 1.0 | 0.01 | 0.056 |
| Spending_Score | -0.327 | 0.01 | 1.0 | -0.058 |
| Gender_Encoded | 0.061 | 0.056 | -0.058 | 1.0 |