1
Dataset Shape

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.

Python 1 import pandas as pd
2 df = pd.read_csv('Mall_Customers.csv')
3 print(df.shape) # Output: (rows, columns)
Result: Shape = 200 rows × 5 columns — 200 customers, 5 features.
2
Column Names

List all column names to understand what data is available before analysis.

Python 1 print(df.columns.tolist())
{'Feature': 'Age', 'count': 200.0, 'mean': 38.85, 'std': 13.97, 'min': 18.0, '25%': 28.75, '50%': 36.0, '75%': 49.0, 'max': 70.0} {'Feature': 'Annual_Income', 'count': 200.0, 'mean': 60.56, 'std': 26.26, 'min': 15.0, '25%': 41.5, '50%': 61.5, '75%': 78.0, 'max': 137.0} {'Feature': 'Spending_Score', 'count': 200.0, 'mean': 50.2, 'std': 25.82, 'min': 1.0, '25%': 34.75, '50%': 50.0, '75%': 73.0, 'max': 99.0} {'Feature': 'Gender_Encoded', 'count': 200.0, 'mean': 0.44, 'std': 0.5, 'min': 0.0, '25%': 0.0, '50%': 0.0, '75%': 1.0, 'max': 1.0}
3
Data Types

Verifying data types ensures that numeric columns aren't stored as strings and that categorical columns are correctly typed.

Python 1 print(df.dtypes)
2 print(df.info())
ColumnTypeSample Value
Gender str Male
Age int64 19
Annual_Income int64 15
Spending_Score int64 39
Gender_Encoded int64 1
4
Missing Values Check

Missing values can cause K-Means to fail or produce incorrect clusters. We check each column for nulls before proceeding.

Python 1 print(df.isnull().sum()) # Count nulls per column
2 print(df.isnull().sum().sum()) # Total nulls
ColumnMissing%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
✅ No missing values detected. All 200 rows are complete.
5
Duplicate Rows

Duplicate rows skew clustering results by creating artificial density in certain regions of the feature space.

Python 1 print(df.duplicated().sum())
2 df = df.drop_duplicates()
Duplicates found: 0 — No duplicates, dataset is clean.
6
Statistical Summary

df.describe() gives count, mean, std, min/max, and quartiles for each numeric column.

Python 1 df.describe().round(2)
FeatureCountMeanStdMin25%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
7
Outlier Detection (IQR Method)

The Inter-Quartile Range (IQR) method detects outliers: values below Q1−1.5×IQR or above Q3+1.5×IQR.

Python 1 Q1, Q3 = df[col].quantile(0.25), df[col].quantile(0.75)
2 IQR = Q3 - Q1 # Inter-Quartile Range
3 outliers = df[(df[col] < Q1-1.5*IQR) | (df[col] > Q3+1.5*IQR)]
FeatureQ1Q3IQRLower FenceUpper FenceOutliers
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
8
Gender Distribution
👩
112
Female
👨
88
Male
9
Feature Value Ranges
FeatureMinMaxMeanMedianStd
Age 18.070.0 38.8536.013.97
Annual_Income 15.0137.0 60.5661.526.26
Spending_Score 1.099.0 50.250.025.82
Gender_Encoded 0.01.0 0.440.00.5
10
Correlation Analysis

Pearson correlation measures linear relationships (−1 to +1). Values near 0 indicate independent features — good for K-Means as we want feature diversity.

Feature AgeAnnual_IncomeSpending_ScoreGender_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
Low correlation between Income and Spending Score (key features) confirms they capture independent dimensions of customer behaviour — ideal for clustering.