Кластеризация с использованием ромашки и пам в R - PullRequest
2 голосов
/ 20 февраля 2020

Я пытаюсь выполнить довольно простой кластерный анализ, но не могу получить правильные результаты. Мой вопрос к большому набору данных: «Какие заболевания часто сообщаются вместе?». Упрощенная выборка данных, приведенная ниже, должна привести к 2 группам: 1) головная боль / головокружение 2) тошнота / боль в животе. Однако я не могу понять код правильно. Я использую функции pam и daisy. Для этого примера я вручную назначаю 2 кластера (k = 2), потому что знаю желаемый результат, но в действительности я исследую несколько значений для k.

Кто-нибудь знает, что я здесь не так делаю?

library(cluster)
library(dplyr)

dat <- data.frame(ID = c("id1","id1","id2","id2","id3","id3","id4","id4","id5","id5"),
                  PTName = c("headache","dizziness","nausea","abd pain","dizziness","headache","abd pain","nausea","headache","dizziness"))


gower_dist <- daisy(dat, metric = "gower")
k <- 2
pam_fit <- pam(gower_dist, diss = TRUE, k)  # performs cluster analysis
pam_results <- dat %>%
  mutate(cluster = pam_fit$clustering) %>%
  group_by(cluster) %>%
  do(the_summary = summary(.))
head(pam_results$the_summary)

1 Ответ

4 голосов
/ 28 февраля 2020

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

Следовательно, нам нужно создать набор данных, в котором в каждом ряду указан пациент со всеми заболеваниями, о которых он сообщил, и затем построить матрицу различий только по признакам чисел c. Для этой задачи я собираюсь добавить столбец presence со значением 1, если пациент сообщает о болезни, 0 в противном случае; нули будут заполняться автоматически функцией pivot_wider ( ссылка ).

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

library(cluster)
library(dplyr)
library(tidyr)

dat <- data.frame(ID = c("id1","id1","id2","id2","id3","id3","id4","id4","id5","id5"),
                  PTName = c("headache","dizziness","nausea","abd pain","dizziness","headache","abd pain","nausea","headache","dizziness"),
                  presence = 1)
# build the wider dataset: each row is a patient
dat_wider <- pivot_wider(
    dat,
    id_cols = ID,
    names_from = PTName,
    values_from = presence,
    values_fill = list(presence = 0)
)

# in the dissimalirity matrix construction, we leave out the column ID
gower_dist <- daisy(dat_wider %>% select(-ID), metric = "gower")
k <- 2

set.seed(123)
pam_fit <- pam(gower_dist, diss = TRUE, k) 
pam_results <- dat_wider %>%
    mutate(cluster = pam_fit$clustering) %>%
    group_by(cluster) %>%
    do(the_summary = summary(.))
head(pam_results$the_summary)

Более того, поскольку вы работаете только с двоичными данными, вместо расстояния Гауэра вы можете рассмотреть возможность использования расстояния Simple Matching или Jaccard если они подходят вашим данным лучше. В R вы можете использовать их, используя

sm_dist <- dist(dat_wider %>% select(-ID), method = "manhattan")/p
j_dist <- dist(dat_wider %>% select(-ID), method = "binary")

соответственно, где p - количество двоичных переменных, которые вы хотите рассмотреть.

...