Время прочтения: 3 мин.

Кластерный анализ решает задачу разбиения множества на группы (кластеры) по принципу наибольшей однородности.

Подобные задачи возникают во множестве сфер деятельности, в частности это реклама и маркетинг. Ситуация, когда нужно выделить группы клиентов, максимально «похожих» друг на друга или определить локации, в которых преобладают определённые предпочтения.

В этой статье я рассмотрю подобный пример и расскажу о способах решения вопроса средствами языка R.

Загружаю датасет из csv-файла. Задача следующая: разбить множества населённых пунктов, участвовавших в рекламной рассылке на сегменты по приоритету подписки на определённый журнал.

adv_dataframe <- read.csv('./advert_dataset.csv', header=T)
head(adv_dataframe)

Вычисляю %-ное  отношение числа подписок к общему количеству рассылок по городу для каждого журнала:

adv_dataframe$'Кот_и_пёс_%' <- 100 * adv_dataframe$'Кот_и_пёс'/ adv_dataframe$'Всего_рассылок'
adv_dataframe$'Дача_%' <- 100 * adv_dataframe$'Дача'/ adv_dataframe$'Всего_рассылок'
adv_dataframe$'Увлекательная_геология_%'<-100*adv_dataframe$'Увлекательная_геология'/ adv_dataframe$'Всего_рассылок'
adv_dataframe$'Домашняя_выпечка_%' <- 100 * adv_dataframe$'Домашняя_выпечка'/ adv_dataframe$'Всего_рассылок'
adv_dataframe$'Психология_%' <- 100 * adv_dataframe$'Психология'/ adv_dataframe$'Всего_рассылок'
df4analysis <- subset(adv_dataframe, select = c('Город','Кот_и_пёс_%','Дача_%','Увлекательная_геология_%','Домашняя_выпечка_%','Психология_%'))

Стандартизирую данные основного датасета. И следом получаю матрицу расстояний (distance_matrix).

pure_data <- df4analysis[,-c(1,1)]
means <- apply(pure_data,2,mean)
sds <- apply(pure_data,2,sd)
norm_ <- scale(pure_data,center=means,scale=sds)
distance_martix = dist(norm_)

Рассмотрим иерархическую кластеризацию.

Построю дендрограмму на основе полученной матрицы расстояний.

df4analysis.hclust<-hclust(distance_martix,method="average") 
plot(df4analysis.hclust)
rect.hclust(df4analysis.hclust , k = 3, border = 2:6)
abline(h = 2.6, col = 'red')

Визуально можно выделить 3 кластера. Так же дополнительно в построении дендрограммы провожу линию на уровне 3 и выделяю кластеры (rect.hclust) разными цветами.

Добавляю в наш основной датасет столбец с признаком принадлежности к кластеру.

cut_ <- cutree(df4analysis.hclust, k = 3)
df4analysis.cut_ = factor(cut_)

Теперь посмотрим и проанализируем результат:

head(df4analysis)

Из получившегося распределения видно, что в кластере 1- два города с преобладанием новых подписок на журналы «Увлекательная геология» и «Домашняя выпечка», в кластере 2- это «Кот и пёс» и «Психология» и в кластере 3- города с преобладанием подписок на журнал «Дача».

Рассмотрим применение метода K-средних (kmeans).

Воспользуюсь методом kmeans, а также добавлю наименования для строк. После применяю метод fviz_cluster библиотеки factoextra для визуализации.

library(factoextra) 
k_ <- kmeans(norm_, centers = 3, nstart = 25)
rownames(norm_) <- df4analysis$'Город'
fviz_cluster(k_, data = norm_)

Результат получается следующим:

В данном случае происходит разбиение множества населённых пунктов на те же 3 кластера (аналогично предыдущему).

Для исследования на оптимум разбиения множества, можно использовать метод  fviz_nbclust библиотеки factoextra.

fviz_nbclust(norm_, kmeans, method = <метод>) 

В качестве параметра method могут выступать значения «gap_stat» (Gap static method), «silhouette»(Silhouette method), «wss» (Elbow method). В качестве результата для анализа fviz_nbclust выдаёт соответствующий параметру method график.

Тема кластеризации невероятно обширна, и в данной статье я познакомил вас с некоторыми основными моментами при решении задачи кластеризации. Вместе с тем, я хотел отметить, как невероятно обширен инструментарий языка R, позволяющий решать эти задачи, зачастую очень небольшим числом строк кода.