-
Notifications
You must be signed in to change notification settings - Fork 2
/
kmeans_clustering_advanced.py
111 lines (69 loc) · 3.81 KB
/
kmeans_clustering_advanced.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
##############################################################################
# IMPORT REQUIRED PACKAGES
##############################################################################
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.preprocessing import MinMaxScaler
##############################################################################
# CREATE THE DATA
##############################################################################
# import tables
transactions = pd.read_excel("data/grocery_database.xlsx", sheet_name = "transactions")
product_areas = pd.read_excel("data/grocery_database.xlsx", sheet_name = "product_areas")
# merge on the product area name
transactions = pd.merge(transactions, product_areas, how = "inner", on = "product_area_id")
# drop the non-food category
transactions.drop(transactions[transactions["product_area_name"] == "Non-Food"].index, inplace = True)
# aggregate sales at customer level (by product area)
transactions_summary = transactions.groupby(["customer_id", "product_area_name"])["sales_cost"].sum().reset_index()
# pivot data to place product areas as columns
transactions_summary_pivot = transactions.pivot_table(index = "customer_id",
columns = "product_area_name",
values = "sales_cost",
fill_value = 0,
margins = True,
margins_name = "Total").rename_axis(None, axis = 1)
# turn sales into % sales
transactions_summary_pivot = transactions_summary_pivot.div(transactions_summary_pivot["Total"], axis = 0)
# drop the "total" column
data_for_clustering = transactions_summary_pivot.drop(["Total"], axis = 1)
##############################################################################
# DATA PREPARATION & CLEANING
##############################################################################
# check for missing values
data_for_clustering.isna().sum()
# normalise data
scale_norm = MinMaxScaler()
data_for_clustering_scaled = pd.DataFrame(scale_norm.fit_transform(data_for_clustering), columns = data_for_clustering.columns)
##############################################################################
# USE WCSS TO FIND A GOOD VALUE FOR K
##############################################################################
k_values = list(range(1,10))
wcss_list = []
for k in k_values:
kmeans = KMeans(n_clusters = k, random_state = 42)
kmeans.fit(data_for_clustering_scaled)
wcss_list.append(kmeans.inertia_)
plt.plot(k_values, wcss_list)
plt.title("Within Cluster Sum Squares - by k")
plt.xlabel("k")
plt.ylabel("WCSS Score")
plt.tight_layout()
plt.show()
##############################################################################
# INSTANTIATE THE MODEL
##############################################################################
kmeans = KMeans(n_clusters = 3, random_state = 42)
kmeans.fit(data_for_clustering_scaled)
##############################################################################
# USE CLUSTER INFORMATION
##############################################################################
# add cluster labels to our data
data_for_clustering["cluster"] = kmeans.labels_
# check cluster sizes
data_for_clustering["cluster"].value_counts()
##############################################################################
# PROFILE CLUSTERS
##############################################################################
cluster_summary = data_for_clustering.groupby("cluster")[["Dairy", "Fruit", "Meat", "Vegetables"]].mean().reset_index()