Как применить иерархический или кластерный анализ k-средних с использованием R?

#r #cluster-analysis

#r #кластерный анализ

Вопрос:

Я хочу применить иерархический кластерный анализ с 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. Я попытался улучшить исходный вопрос, потому что (и я не независимый наблюдатель, но …) Я думаю, что ответы здесь, по крайней мере, полезны и заслуживают того, чтобы остаться здесь. Пожалуйста, помогите, отредактировав его, если вы можете улучшить дальше.

2. @Гэвин Симпсон: Ты святой, и я вновь открыл вопрос. Я также удалил все ранее опубликованные комментарии, поскольку они больше не актуальны (не говоря уже о реальном бельме на глазу), и уберу их, как только вы их увидите.

3. Действительно ли имеет смысл в значительной степени заменять устаревший вопрос, которому больше года, и на который следует ответить знаменитым «прочитайте руководство» или «Google для «hclust R tutorial»»? Кроме того, я не удивлюсь, если здесь уже есть 10 дубликатов.

4. Затем закройте вопрос как дублирующий. Затем ответ может быть объединен или сохранен. Если бы не было хороших ответов, я бы согласился, но есть, и люди пытались удалить это только из-за качества вопроса. По крайней мере, вопрос теперь не воняет. Совет по Meta — делать то, что я сделал.

5. @BoltClock Спасибо за это. Я также отредактировал ответ, чтобы он больше соответствовал отредактированному вопросу. Комментарий к ответу теперь не помешало бы прояснить, если у вас будет такая возможность. Я могу удалить некоторые из своих, но те, что находятся в OP, потребуют некоторого внимания к модификации. Будет отмечено позже.

Ответ №1:

Для иерархического кластерного анализа внимательно ознакомьтесь с ?hclust и запустите его примеры. Альтернативные функции находятся в пакете cluster, который поставляется с R. Кластеризация k-means доступна в function 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)
  

дендрограмма

Допустим, нам нужно 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
  

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

Комментарии:

1. @sridher ошибка, загрузите свои данные в R. Существует множество способов сделать это в зависимости от формата ваших данных. Я думаю, вам нужно сделать шаг назад и прочитать некоторые вводные руководства по R, а именно «Введение в R» и руководство «Импорт / экспорт данных R», оба доступны здесь: cran.r-project.org/manuals.html

2. Мой набор данных состоит из csv-файла …. я импортировал его в консоль, используя эту функцию > data1 <- read.csv(file.choose(), header = TRUE) теперь data1 — это мой набор данных… с этого момента я не могу этого сделать …. пожалуйста, можете ли вы объяснить упоминание этой переменной data1, чтобы я мог получать кластеры…

3. извините, что беспокою вас … но моя голова только что предоставила огромный набор данных и попросила меня сделать это за 2 дня 🙁 …. но я совершенно новичок в этом … пожалуйста, не обращайте внимания на глупые вопросы… но для меня это не глупо!

4. Итак, в моем коде dat играет роль ваш data1 . Итак, посмотрите на мой код и замените dat на data1 во всех вызовах функций. Теперь, сработает это или нет, будет зависеть от того, какие типы данных есть в вашем, data1 и поскольку у меня их нет data1 , я не могу сказать, будет ли код работать с вашими данными или нет.

5. Это самое высокое соотношение качества ответа / вопроса, которое я видел за последнее время.