Как применить иерархический или k-средний кластерный анализ с использованием R? - PullRequest
0 голосов
/ 13 апреля 2011

Я хочу применить иерархический кластерный анализ с R. Я знаю о функции hclust(), но не знаю, как использовать это на практике; Я застрял с передачей данных в функцию и обработкой вывода.

Я также хотел бы сравнить иерархическую кластеризацию с созданной kmeans(). Опять же, я не уверен, как вызвать эту функцию или использовать / манипулировать выводом из нее.

Мои данные похожи на:

## dummy data
require(MASS)
set.seed(1)
dat <- data.frame(mvrnorm(100, mu = c(2,6,3), 
                          Sigma = matrix(c(10,   2,   4,
                                            2,   3, 0.5,
                                            4, 0.5,   2), ncol = 3)))

1 Ответ

60 голосов
/ 13 апреля 2011

Для иерархического кластерного анализа внимательно посмотрите на ?hclust и запустите его примеры. Альтернативные функции находятся в пакете cluster , который поставляется вместе с R. k означает, что кластеризация доступна в функции kmeans(), а также в пакете cluster.

Простой иерархический кластерный анализ показанных вами фиктивных данных будет сделан следующим образом:

## dummy data first
require(MASS)
set.seed(1)
dat <- data.frame(mvrnorm(100, mu = c(2,6,3), 
                          Sigma = matrix(c(10,   2,   4,
                                            2,   3, 0.5,
                                            4, 0.5,   2), ncol = 3)))

Вычислить матрицу различий, используя евклидовы расстояния (вы можете использовать любое расстояние, которое хотите)

dij <- dist(scale(dat, center = TRUE, scale = TRUE))

Затем сгруппируйте их, скажем, используя групповой средний иерархический метод

clust <- hclust(dij, method = "average")

Печать результата дает нам:

R> clust

Call:
hclust(d = dij, method = "average")

Cluster method   : average 
Distance         : euclidean 
Number of objects: 100
Plot the dendrogram

но этот простой вывод противоречит сложному объекту, который нуждается в дополнительных функциях для извлечения или использования содержащейся в нем информации:

R> str(clust)
List of 7
 $ merge      : int [1:99, 1:2] -12 -17 -40 -30 -73 -23 1 -52 -91 -45 ...
 $ height     : num [1:99] 0.0451 0.0807 0.12 0.1233 0.1445 ...
 $ order      : int [1:100] 84 14 24 67 46 34 49 36 41 52 ...
 $ labels     : NULL
 $ method     : chr "average"
 $ call       : language hclust(d = dij, method = "average")
 $ dist.method: chr "euclidean"
 - attr(*, "class")= chr "hclust"

Дендрограмму можно сгенерировать с помощью метода plot() (hang получает метки внизу дендрограммы вдоль оси x, а cex просто сжимает все метки до 70% или нормально)

plot(clust, hang = -0.01, cex = 0.7)

dendrogram

Скажем, мы хотим 3-кластерное решение, отрежьте дендрограмму, чтобы получить 3 группы и вернуть членство в кластере

R> cutree(clust, k = 3)
  [1] 1 2 1 2 2 3 2 2 2 3 2 2 3 1 2 2 2 2 2 2 2 2 2 1 2 3 2 1 1 2 2 2 2 1 1 1 1
 [38] 2 2 2 1 3 2 2 1 1 3 2 1 2 2 1 2 1 2 2 3 1 2 3 2 2 2 3 1 3 1 2 2 2 3 1 2 1
 [75] 1 2 3 3 3 3 1 3 2 1 2 2 2 1 2 2 1 2 2 2 2 2 3 1 1 1

То есть cutree() возвращает вектор такой же длины, что и количество кластеризованных наблюдений, элементы которых содержат идентификатор группы, которой принадлежит каждое наблюдение. Членство - это идентификатор листа, в который попадает каждое наблюдение, когда дендрограмма разрезается на заданной высоте или, как здесь сделано, на соответствующей высоте, чтобы обеспечить указанное количество групп.

Возможно, этого достаточно для продолжения?

Для k -средств мы бы сделали это

set.seed(2) ## *k*-means uses a random start
klust <- kmeans(scale(dat, center = TRUE, scale = TRUE), centers = 3)
klust

что дает

> klust
K-means clustering with 3 clusters of sizes 41, 27, 32

Cluster means:
           X1          X2          X3
1  0.04467551  0.69925741 -0.02678733
2  1.11018549 -0.01169576  1.16870206
3 -0.99395950 -0.88605526 -0.95177110

Clustering vector:
  [1] 3 1 3 2 2 3 1 1 1 1 2 1 1 3 2 3 1 2 1 2 2 1 1 3 2 1 1 3 3 1 2 2 1 3 3 3 3
 [38] 1 2 2 3 1 2 2 3 3 1 2 3 2 1 3 1 3 2 2 1 3 2 1 2 1 1 1 3 1 3 2 1 2 1 3 1 3
 [75] 3 1 1 1 1 1 3 1 2 3 1 1 1 3 1 1 3 2 2 1 2 2 3 3 3 3

Within cluster sum of squares by cluster:
[1] 47.27597 31.52213 42.15803
 (between_SS / total_SS =  59.3 %)

Available components:

[1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
[6] "betweenss"    "size"

Здесь мы получаем некоторую информацию о компонентах в объекте, возвращаемую kmeans(). Компонент $cluster даст вектор принадлежности, сравнимый с выводом, который мы видели ранее из cutree():

R> klust$cluster
  [1] 3 1 3 2 2 3 1 1 1 1 2 1 1 3 2 3 1 2 1 2 2 1 1 3 2 1 1 3 3 1 2 2 1 3 3 3 3
 [38] 1 2 2 3 1 2 2 3 3 1 2 3 2 1 3 1 3 2 2 1 3 2 1 2 1 1 1 3 1 3 2 1 2 1 3 1 3
 [75] 3 1 1 1 1 1 3 1 2 3 1 1 1 3 1 1 3 2 2 1 2 2 3 3 3 3

В обоих случаях обратите внимание, что я также масштабирую (стандартизирую) данные, чтобы можно было сравнивать каждую переменную в общем масштабе. С данными, измеренными в разных «единицах» или в разных масштабах (как здесь с разными средними и отклонениями), это важный шаг обработки данных, если результаты должны быть значимыми или не доминировать переменными, которые имеют большие отклонения.

...