Clustering customers using K-means in R | Towards Data Science

A marketer’s job is to find the patterns and the common characteristics of customers to do their segmentation. This is the first step before you come up with the right messages and the channels to communicate and build lasting relationships with customers.
Segmenting customers with common characteristics is not easy and includes a lot of human efforts and intelligence.
The latest developments in machine learning algorithms gave us a new toolset to use a machine to find patterns in a dataset and create clusters. Unsupervised Learning K-means algorithm searches hidden patterns in the dataset (that is not visible for humans) and assigns each observation to the relevant clusters. We will use R for K-means clustering.
The dataset is taken from the Kaggle. It contains information about customers of a retail shopping website. The dataset has 10 variables and 1000 records (before data clean up). Let’s look at dataset details:
The dataset has 8 categorical and 2 continuous variables (Salary and Amount Spent). Due to a lot of missing values, we will remove the History variable leaving us with 7 categorical variables. Also, removing rows with missing values leaving us with 994 records. We are still fine :)
Let’s change factor levels of categorical variables into integers. E.g. for Age set Young=0, Middle=1 and Old=2. For Gender set Female =0, Male=1 and the same for other categorical variables.
cor.matrix <- cor(data, method = "pearson", use = "complete.obs")corrplot(cor.matrix)
Analyzing the correlation matrix of the 9 variables (7 categorical & 2 continuous) reveals us some intuitive insights and some which are surprising:
Both Married and Salary, as well as, AmountSpent and Salary are highly correlated positively.
Children (number of children) and Age are negatively correlated, in the dataset, older people have a small number of children — either 0 or 1.
Another surprising insight coming from the correlation matrix is that Married and Children — they are not correlated. After looking into it we found out that married and singles have about the same amount of children.
Less surprising and more intuitive of no correlation is apparent between Gender and Age.
We have very interesting customers shopping on the website :)
How many clusters do we need? To determine this let’s use the Elbow method, Silhouette Score and Calinski-Harabasz Index. One method may not give us a clear answer. This is why we need to try another method to decide the right number of clusters.
There are ready formulas in R for these methods, we just need to apply to our dataset.
Elbow method:
R code for this method:
The result of the above R codes is displayed in the graph below. Looking at the graph it is hard to decide what is an optimal number of clusters. 2, 3 or 4? hmm... hard to say... Let’s use another method.
Silhouette Score:
R code:
opt.k.sil <- Optimal_Clusters_KMeans(data, max_clusters=10, plot_clusters = TRUE, criterion = "silhouette")
The results are in the below graph. The higher Silhouette Score gives us an indication of an optimal number of clusters. In our case, both 2 and 4 numbers of clusters have the highest scores, but the problem is that both are the same and we cannot decide which one to choose :(. Let’s move to the Calinski-Harabasz Index.
Calinski-Harabasz Index:
R code:
The higher Calinski-Harabasz Index determines which the number of clusters to choose. It is obvious now that 4 clusters would be the best :)
R code for K-means algorithm:
KMC <- kmeans(data, centers = 4, iter.max = 999, nstart=50)
After applying the algorithm let’s see how many customers are in each cluster:
Clusters 1, 2, 4 are distributed almost evenly with 269, 285 and 283 customers respectively, while cluster number 3 has 157 customers.
Cluster 1 — mostly young single women with no children, who live in rent. The cluster has the lowest average salary and the lowest average amount spent.
Cluster 2 — middle age and old men and women, with mostly no or a single child who buy mid-range products. The second-lowest average salary and amount spent.
Cluster 3 — mostly middle-aged men, own homes. Every single person in the cluster is married. Relative to the other clusters they have the highest ratio of 2 and 3 children. They made the highest salaries and spend the most.
Cluster 4 — middle age who mostly own homes and are married. Buy high-end products and spend the second-highest amount.
The characteristics of each cluster are highly distinctive and create almost homogeneous segments. It’s easy to notice that Cluster 1 has the “least valuable” customers when it comes to generating money, however, we have no data about the purchasing frequency of this segment. But the picture that depicted from this segment is of a young female student, who doesn’t make a lot of money and doesn’t spend it either.
Cluster 2 is middle age and old customers who don’t make a lot of money and don’t spend much, almost similar to Cluster 4 but these middle-age do have high salaries and do spend a lot, mostly on high-end products.
Cluster 3, on the other hand, are middle-aged men, who have a steady high income, have children and spend the highest amount.
Now it's upon us what will be a strategy to target each cluster.
This story is based on the project that was done together with my colleague Noam Shmuel during the class of “Unsupervised Learning” @University of Warsaw taught by professor Jacek Lewkowicz, PhD
Full R codes and the database are on my GitHub.
[1] A. Rezaeian, S. Shokouhyar, and F. Dehghan, Measuring Customers Satisfaction of E-Commerce Sites Using Clustering Techniques: Case Study of Nyazco Website. International Journal of Management, Accounting and Economics, (2016), 3(1), 61–74.
[2] A. Sagar, Customer Segmentation Using K Means Clustering (2019), towardsdatascience.com
[3] Dataflair Team, Data Science Project — Customer Segmentation using Machine Learning in R (2019)
[4] R package description on cran.r-project.org: An Introduction to corrplot Package and RFM Analysis in R on r-blogger
[5] The Dataset was taken from Kaggle.com