Cluster Analysis
Cluster Analysis
library(ggplot2)
La segmentazione dei clienti è una delle aree di business in cui i metodi di clustering possono essere molto
utili. Grazie a questa tecnica di apprendimento senza supervisione, un’azienda può adattare la strategia di
marketing in modo più efficiente e concentrarsi su quei clienti che garantiranno le entrate più elevate.
Vedremo come implementare 2 diversi algoritmi di clustering (k-means e clustering gerarchico) per segmentare
i clienti in diversi gruppi, in base alle loro spese e al loro reddito.
Utilizzeremo i seguenti pacchetti 1) cluster : per il calcolo degli algoritmi di raggruppamento 2) factoextra:
per un’elegante visualizzazione dei risultati
1
Rinomiamo le variabili (in italiano) Inoltre, escludiamo la variabile “CustomerID” poiché il focus in quest’analisi
è sui gruppi di clienti e quindi le informazioni sull’identificativo dei clienti non è utile in questo caso.
names(customers)[2] <- paste('Genere')
names(customers)[3] <- paste('Età')
names(customers)[4] <- paste('Redditoannuo')
names(customers)[5] <- paste('Punteggiospesa')
customers <- customers[,2:5]
summary(customers)
10
count
20 30 40 50 60 70
Età
Guardando l’età dei clienti, si può vedere che il gruppo più numeroso è costituito da persone dai 30 ai 35
anni (più di 35 membri). La distribuzione di questa variabile è distorta a destra, quindi ci sono molte più
2
persone sul lato sinistro (40 anni o più giovani) che sul lato destro.
ggplot(customers, aes(x=Redditoannuo))+
geom_histogram(color="orange", fill="green",binwidth=5)+labs(title="Reddito annuo dei clienti")
15
10
count
50 100
Redditoannuo
Quando si tratta di reddito annuale dei clienti, la distribuzione sembra in qualche modo simile a quella
precedente, sebbene la differenza tra il lato sinistro e il lato destro dell’istogramma sia ancora maggiore. Ci
sono molti clienti che guadagnano fino a 80 mila all’anno.
ggplot(customers, aes(x=Punteggiospesa))+
geom_histogram(color="red", fill="orange",binwidth=5)+labs(title="Punteggio spesa dei clienti")
3
Punteggio spesa dei clienti
20
15
count
10
0 25 50 75 100
Punteggiospesa
Infine, il punteggio di spesa dei clienti assomiglia di più alla normale distribuzione di questi tre. La maggior
parte delle osservazioni sono concentrate intorno alla media (50) ed entrambi i lati del grafico sembrano
molto simili. Ciò che è interessante, ci sono molte osservazioni su entrambe le estremità, il che significa che ci
sono molti clienti che spendono molto poco o molto.
Proseguiamo nell’analisi tracciando il reddito annuale ed il punteggio spesa rispetto all’età e al genere. Questo
tipo di analisi potrebbe consentire di trarre altre conclusioni sui dati dei clienti del centro commerciale.
ggplot(customers) +
geom_point(aes(x = Età, y = Redditoannuo, col = Genere))
4
100
Redditoannuo
Genere
Female
Male
50
20 30 40 50 60 70
Età
ggplot(customers) +
geom_point(aes(x = Età, y = Punteggiospesa, col = Genere))
5
100
75
Punteggiospesa
Genere
50 Female
Male
25
20 30 40 50 60 70
Età
ggplot(customers) +
geom_point(aes(x = Redditoannuo, y = Punteggiospesa, col = Genere))
6
100
75
Punteggiospesa
Genere
50 Female
Male
25
50 100
Redditoannuo
Dal primo grafico, possiamo concludere che il reddito più alto può essere osservato per le persone di età
compresa tra i 30 ei 50 anni. Dal secondo grafico scopriamo che tutti i “big spenders” non hanno più di
40 anni. I clienti di età superiore a questa età tendono ad essere più frugali in quanto i valori più alti di
Punteggio spesa sono di circa 60 punti. Infine dall’ultimo grafico vediamo che le osservazioni tendono a
raggrupparsi in un paio di aree del grafico. C’è un gruppo numeroso proprio nel mezzo e pochi gruppi negli
angoli di questa rappresentazione grafica. Il genere sembra avere scarso effetto quando si analizzano il reddito
e la spesa dei clienti.
K-means clustering
Utilizzeremmo dapprima l’algoritmo delle k-medie. Abbiamo visto attraverso l’analisi esplorativa precedente
che due variabili: RedditoAnnuo Punteggio Spesa sono quella che influenzano maggiormente il comportamento
dei consumatori.
Pertanto i cluster verranno generati solo sulla base di queste due variabili.
Il metodo delle k medie richiede che l’analista specifichi il numero di clusters da generare.
7
fviz_nbclust(customers[, 3:4], kmeans, method = "wss") +
geom_vline(xintercept = 5, linetype = 2)
2e+05
1e+05
1 2 3 4 5 6 7 8 9 10
Number of clusters k
8
1.0 1
0.9
0.8
variance_explained
0.7 0.69
0.6
0.5
0.4 0.39
0.3 0.27
0.2
0.16 0.14 0.13 0.12
0.1 0.1 0.08
1 2 3 4 5 6 7 8 9 10
clusters
Dal grafico sopra, è abbastanza difficile definire chiaramente dove si trova il “gomito”.
metodo silhoutte Si può utilizzare ancora un altro metodo chiamato “silhouette” per identificare il numero
di cluster. Misura quanto è simile un oggetto al proprio cluster rispetto ad altri cluster. Traccereremo il valore
medio di sillhoute per k compreso tra 2 e 10 e il valore più alto ricevuto dovrebbe aiutarci a determinare il
numero ottimale di cluster.
opt <- Optimal_Clusters_KMeans(customers[, 3:4], max_clusters = 10, plot_clusters = T, criterion = 'silh
9
0.55 0.54 0.54
0.52
0.50 0.5
0.45 0.46 0.46 0.45 0.45
0.40
0.35
silhouette
0.30 0.31
0.25
0.20
0.15
0.10
0.05
0.00 0
1 2 3 4 5 6 7 8 9 10
clusters
Il valore di sillhoute medio più alto (pari a 0,54) è presente per k = 5. Pertanto dovremmo optare per 5
cluster nella nostra ulteriore analisi con l’algoritmo delle k-means. Nella fase successiva aggiungeremo il
numero di cluster a ciascuna osservazione nel nostro dataframe e tracciamo le osservazioni rispetto al loro
cluster con ggplot.
Nella funzione kmeans possiamo passargli i seguenti argomenti:
Arguments x:numeric matrix, numeric data frame or a numeric vector centers: Possible values are the number
of clusters (k) or a set of initial(distinct) cluster centers. If a number, a random set of (distinct) rows in x
is chosen as the initial centers. [Link]:The maximum number of iterations allowed. Default value is 10.
nstart : The number of random starting partitions when centers is a number. Trying nstart ¿ 1 is often
recommended.
[Link](22)
km <- kmeans(customers[,3:4], 5)
customers$ClusterNumber <- km$cluster
ggplot(customers[,3:5]) +
geom_point(aes(x = Redditoannuo, y = Punteggiospesa, col = [Link](ClusterNumber))) +
scale_color_discrete(name="Cluster Number")
10
100
75
Cluster Number
Punteggiospesa
1
2
50
3
4
5
25
50 100
Redditoannuo
Il grafico sopra indica chiaramente che l’algoritmo k-means ha distinto 5 gruppi di clienti. Ci sono 2 diversi
gruppi di clienti sul lato sinistro, con redditi piccoli e punteggi di spesa alti in uno dei gruppi e bassi nell’altro.
Allo stesso modo, possiamo vedere 2 gruppi che si sono formati sul lato destro del nostro grafico, questa volta
includendo il fatto che i guadagni sono al di sopra della media. Infine, c’è un gruppo a metà, con clienti che
hanno guadagni annuali medi e anche le loro abitudini di spesa sono in qualche modo al centro dell’intera
popolazione.
11
## 3 Female 20 16 6 3 3
## 4 Female 23 16 77 4 4
## 5 Female 31 17 40 3 3
## 6 Female 22 17 76 4 4
###ACCESSO AI RISULTATI DELLA FUNZIONE KMEANS
La funzione kmeans() ha come output una lista con i seguenti componenti
cluster:A vector of integers (from 1:k) indicating the cluster to which each point is allocated
centers: A matrix of cluster centers (cluster means) (distinct) rows in x is chosen as the initial centers.
totss:The total sum of squares (TSS)
withinss:Vector of within-cluster sum of squares
betweenss:The between-cluster sum of squares
size::The number of observations in each cluster
km$size
## [1] 35 81 23 22 39
## Warning: ggrepel: 113 unlabeled data points (too many overlaps). Consider
## increasing [Link]
12
Cluster plot
46 178 188
18 44 a 1
170
28 143 a 2
0
147 a 3
5 21 185
27 161 a 4
1 43
169 181 197
17 41 45 133 a 5
187
−1 19 29 39 125 165
13 25 191
37 149
11 15 189 195 199
7 23 35 163
183
3 193
−2 9 31 33
159 157
−2 −1 0 1 2 3
Redditoannuo
CLUSTERING GERARCHICO
In questa parte dell’analisi della segmentazione dei clienti, utilizzereremo il clustering gerarchico agglomerativo
(noto anche come approccio bottom-up), un metodo utilizzato per raggruppare gli oggetti in base alla loro
somiglianza. All’inizio ogni osservazione inizia nel proprio cluster e, passo dopo passo, le coppie di cluster
vengono unite man mano che si sale nella gerarchia. Prima di implementare l’algoritmo di clustering, si
confronteranno le distanze tra i punti dati e nella fase successiva verrà utilizzata la funzione “hclust” per
eseguire l’analisi del cluster.
dist_customers <- dist(customers[,3:4])
hc_customers <- hclust(dist_customers, method = 'complete')
Output della funzione hclust $merge:sequenza del processo di fusione $height:vettore che indica il livello
di distanza attraverso il quale e avvenuta la fusione, la cui lunghezza equivale al numero di
iterazioni $order: opportuna permutazione delle unità finalizzata alla costruzione del
dendrogramma $labels: l’etichetta che contrassegna le unit
Occorrerà scegliere il numero ottimale di cluster, Per fare ciò, analogamente al metodo k-means, si potrà
utilizzare il criterio silhouette.
library(cluster)
13
}
0.0 0.2 0.4 0.6 0.8 1.0 −0.2 0.0 0.2 0.4 0.6 0.8 1.0
Silhouette width si Silhouette width si
Average silhouette width : 0.37 Average silhouette width : 0.46
−0.2 0.0 0.2 0.4 0.6 0.8 1.0 0.0 0.2 0.4 0.6 0.8 1.0
Silhouette width si Silhouette width si
Average silhouette width : 0.49 Average silhouette width : 0.55
−0.2 0.0 0.2 0.4 0.6 0.8 1.0 −0.2 0.0 0.2 0.4 0.6 0.8 1.0
Silhouette width si Silhouette width si
Average silhouette width : 0.54 Average silhouette width : 0.54
Anche in questo caso dovremo optare per 5 cluster poichè la larghezza media della silhoutte è la più grande
per k=5.
DENDROGRAMMA
Tracciamo il dendrogramma. Per renderlo più significativo possiamo utilizzare colori diversi per indicare
quale osservazioni ricadono in quale cluster.
library(dendextend)
##
## ---------------------
## Welcome to dendextend version 1.16.0
## Type citation('dendextend') for how to cite the package.
##
14
## Type browseVignettes(package = 'dendextend') for the package vignette.
## The github page is: [Link]
##
## Suggestions and bug-reports can be submitted at: [Link]
## You may ask questions at stackoverflow, use the r and dendextend tags:
## [Link]
##
## To suppress this message use: suppressPackageStartupMessages(library(dendextend))
## ---------------------
##
## Attaching package: 'dendextend'
## The following object is masked from 'package:stats':
##
## cutree
clust_customers <- cutree(hc_customers, k = 5)
dend_customers <- [Link](hc_customers)
dend_colored <- color_branches(dend_customers, k = 5)
par(mfrow = c(1, 1))
plot(dend_colored)
120
20 40 60 80
0
12
20
34
8
42
36
26
30
14
2
4
6
16
38
40
28
32
22
24
10
18
15
11
13
25
9
3
7
35
37
23
31
33
41
43
39
45
27
1
5
29
19
17
21
101
106
95
99
117
109
92
94
113
119
122
143
147
161
125
127
133
123
120
121
112
104
105
103
118
79
81
82
76
77
88
91
85
87
89
86
75
78
90
97
107
111
100
96
115
116
93
98
102
110
108
114
52
54
44
46
47
51
53
64
66
69
61
62
71
74
72
84
80
83
57
65
67
59
63
73
60
68
70
56
49
50
48
55
193
195
197
58
199
149
153
145
151
155
163
157
159
141
135
137
139
129
131
181
185
189
187
191
167
165
169
173
177
171
175
179
183
200
196
198
148
160
154
158
126
130
132
134
138
140
162
152
150
156
136
144
124
128
164
142
146
188
192
166
172
170
178
190
194
176
168
174
186
180
182
184
15
## grp
## 1 2 3 4 5
## 23 21 85 39 32
# Taglia in 5 gruppi e li colora in base al gruppo
fviz_dend(hc_customers, k = 5, cex = 0.5, k_colors = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07","#FC4E
rect = TRUE # Aggiunge un rettangolo intorno ai clusters
)
Cluster Dendrogram
150
100
Height
50
0
12
8
20
34
42
36
26
30
2
4
14
6
16
38
40
28
32
22
24
10
18
15
11
13
9
3
25
7
35
37
23
31
33
41
43
39
45
1
27
5
29
19
17
21
101
106
95
99
92
94
117
109
113
119
122
143
147
161
125
127
133
123
120
121
112
104
105
103
118
79
81
82
76
77
88
91
85
87
89
86
75
78
90
97
107
111
100
96
93
98
115
116
102
110
108
114
52
54
44
46
47
51
53
64
66
69
61
62
71
74
72
84
80
83
57
65
67
59
63
73
60
68
70
56
49
50
48
55
193
58
195
197
199
149
153
145
151
155
163
157
159
141
135
137
139
129
131
181
185
189
187
191
167
165
169
173
177
171
175
179
183
200
196
198
148
160
154
158
126
130
132
134
138
140
162
152
150
156
136
144
124
128
164
142
146
188
192
166
172
170
178
190
194
176
168
174
186
180
182
184
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
16
segment_customers <- mutate(customers, cluster = clust_customers)
segment_customers = subset(segment_customers, select = -c(ClusterNumber))
ggplot(segment_customers, aes(x = Redditoannuo, y = Punteggiospesa, color = factor(cluster))) +
geom_point() +
scale_color_discrete(name = 'Cluster number')
100
75
Cluster number
Punteggiospesa
1
2
50
3
4
5
25
50 100
Redditoannuo
Il grafico presentato è molto simile a quello che abbiamo ottenuto con il clustering k-means. Tranne un paio
di osservazioni che ora sono nel gruppo con punteggio di spesa medio e reddito annuo, tutte le altre sono
negli stessi gruppi del raggruppamento precedente. Infine, possiamo scoprire quali sono le caratteristiche di
ciascuno dei gruppi esplorando il dataframe “segment_customers”.
segment_customers %>% group_by(cluster, Genere) %>%
summarise_all(list(mean)) %>% arrange(cluster)
## # A tibble: 10 x 5
## # Groups: cluster [5]
## cluster Genere Età Redditoannuo Punteggiospesa
## <int> <chr> <dbl> <dbl> <dbl>
## 1 1 Female 43.2 27.4 21.7
## 2 1 Male 48.3 24.7 19.7
## 3 2 Female 25.6 24.6 81.8
## 4 2 Male 25 25.8 77.7
## 5 3 Female 40.5 55.8 48.6
## 6 3 Male 45.4 55.9 49.9
## 7 4 Female 32.2 86.0 81.7
## 8 4 Male 33.3 87.1 82.7
## 9 5 Female 43.8 93.3 20.6
17
## 10 5 Male 38.8 86.4 11.7
Nel primo gruppo abbiamo donne e uomini di mezza età, il cui reddito annuo e il cui punteggio di spesa
sono bassi. Nel secondo gruppo abbiamo giovani donne e uomini, che nonostante non abbiano molto reddito,
tendono a spendere molto. Il terzo gruppo è il più numeroso, che si trovava proprio al centro dei grafici
presentati. Questo gruppo è composto da donne e uomini sulla quarantina, che ottengono uno stipendio
medio e hanno abitudini di spesa moderate. Nel gruppo numero 4, ci sono per lo più persone sulla trentina
che guadagnano molto e tendono anche a spendere molto. Nell’ultimo gruppo (numero 5), possiamo vedere
donne la cui età media era di circa 44 anni e uomini con età media intorno ai 39 anni. Questo gruppo di
persone, analogamente a quelle del gruppo numero 4, ha redditi annui elevati, ma al contrario, non ama
spendere molto.
Tutto sommato questa tabella ci ha mostrato quante informazioni importanti possiamo ottenere dall’analisi
di clustering.
In questo esempio abbiamo preso in considerazione un caso semplice bidimensionale che non sarebbe lo
scenario nella maggior parte dei casi d’uso aziendali. Tuttavia, questi metodi, con qualche altra analisi
aggiuntiva, possano essere implementati con successo per problemi aziendali reali.
18