Этот проект посвящен кластеризации клеток рака молочной железы с использованием набора данных Висконсинского диагностического рака молочной железы (WDBC). Этот набор данных содержит 10 различных характеристик образцов клеток из скрининговых тестов на рак молочной железы. Эти особенности включают в себя некоторые характеристики клеточных ядер и среды клеток.

Этот проект реализован в R Studio. Сначала был загружен набор данных WDBC и проведен предварительный анализ структуры набора данных.

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

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

wdbc <- read_csv("wdbc.data", col_names = FALSE)
wdbc <- wdbc[1:12]
names(wdbc) <- c("ID", "Diagnosis", "radius", "texture", "perimeter", "area", "smoothness", "compactness", "concavity", "concave.points", "symmetry", "fractal.dimension" )
df <- wdbc[3:12]

Набор данных WDBC выбирает 10 столбцов, связанных с признаками раковых клеток, и переименовывает их для кластерного анализа в R Studio.

summary(df)

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

par(mfrow=c(2,5))
for (i in 1:ncol(df)) {
boxplot(df[i], main = names(df)[i])
}

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

КОРРЕЛЯЦИОННЫЙ АНАЛИЗ

corr <- cor(df)
corrplot(corr )

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

corr
                      radius     texture  perimeter       area  smoothness
radius             1.0000000  0.32905191  0.9978429  0.9874887  0.16252908
texture            0.3290519  1.00000000  0.3348467  0.3249314 -0.01686064
perimeter          0.9978429  0.33484667  1.0000000  0.9866392  0.19962065
area               0.9874887  0.32493143  0.9866392  1.0000000  0.17138316
smoothness         0.1625291 -0.01686064  0.1996206  0.1713832  1.00000000
compactness        0.5045010  0.23977212  0.5555185  0.4971456  0.65922498
concavity          0.6759004  0.30555180  0.7154316  0.6851828  0.52090080
concave.points     0.8220306  0.29698478  0.8506045  0.8227435  0.55227835
symmetry           0.1456362  0.07330473  0.1810399  0.1496752  0.55839052
fractal.dimension -0.3144104 -0.07535031 -0.2641085 -0.2849760  0.58690456
                  compactness concavity concave.points   symmetry
radius              0.5045010 0.6759004      0.8220306 0.14563616
texture             0.2397721 0.3055518      0.2969848 0.07330473
perimeter           0.5555185 0.7154316      0.8506045 0.18103992
area                0.4971456 0.6851828      0.8227435 0.14967519
smoothness          0.6592250 0.5209008      0.5522783 0.55839052
compactness         1.0000000 0.8828571      0.8307113 0.60203791
concavity           0.8828571 1.0000000      0.9212134 0.49989995
concave.points      0.8307113 0.9212134      1.0000000 0.46159597
symmetry            0.6020379 0.4998999      0.4615960 1.00000000
fractal.dimension   0.5650475 0.3361432      0.1659497 0.47952809
                  fractal.dimension
radius                  -0.31441035
texture                 -0.07535031
perimeter               -0.26410849
area                    -0.28497597
smoothness               0.58690456
compactness              0.56504749
concavity                0.33614320
concave.points           0.16594972
symmetry                 0.47952809
fractal.dimension        1.00000000

Самая высокая положительная корреляция наблюдается между радиусом и периметром. Большой коэффициент 0,99. Наибольшая отрицательная корреляция между радиусом и фрактальной размерностью. Большое число, например -0,31. Самая низкая корреляционная гладкость
между текстурой и текстурой. Вроде -0,02. В целом данные очень взаимосвязаны, поэтому корреляции высокие.

data_pca <- prcomp(df, center = TRUE, scale. = TRUE)
summary(data_pca)

Стандартное отклонение компонента PC1 равно 2,3406. Это показывает, что PC1 объясняет большую часть изменчивости в наборе данных.
Компонент PC1 объясняет 54,79 % дисперсии в наборе данных. Компонент PC2 объясняет 25,19% дисперсии в наборе данных, объясняющей дисперсию.
Согласно значению кумулятивной доли, первые два компонента объясняют 79,97% дисперсии в наборе данных.
Имеет смысл выбрать достаточно компонентов, чтобы объяснить 70–80%. В этом выводе первые два компонента объясняют 79,97 % общей дисперсии.
Имеет смысл выбрать два компонента для ее объяснения.

data_pca$rotation[,1:3]

Функция, которая больше всего влияет на компонент PC1, — это concave.points. Наименее фрактальная размерность. Функция, которая вносит наибольший вклад в компонент PC2, вносит свой вклад в функцию fractal.dimension.
Меньше всего вогнутых точек. Функция, которая вносит наибольший вклад в переменную текстуру PC3 Функция текстуры не выражается никаким другим компонентом.

Компонент PC3 выражает только переменную текстуры
. Для этого имеет смысл продолжить работу с двумя компонентами.

fviz_pca_ind(data_pca,
col.ind = "cos2",
gradient.cols = c("black", "yellow", "red"),
repel = TRUE)

Судя по графику, справа вверху и справа внизу есть кластеризация.
По значениям 109-го наблюдения слева внизу значения близкие к максимальным по признакам, кроме Радиуса и Текстуры
По 179-му наблюдению значения на противоположной оси гладкости и вогнутости имеют значения, близкие к минимальным.

fviz_pca_var(data_pca,
col.var = "contrib",
gradient.cols = c("black", "yellow", "red"),
repel = TRUE )

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

ДИСТАНЦИОННЫЕ ИНТЕРПРЕТАЦИИ

dist_euc <- get_dist(df, stand = TRUE)
fviz_dist(dist_euc)

Согласно тепловой карте матрицы расстояний, есть участки с кластеризацией.

dist_euc[which.max(dist_euc)]
dist_euc[which.min(dist_euc)]
## [1] 14.26571
## [1] 0.3106926

Расстояние между двумя наиболее удаленными друг от друга наблюдениями равно 14,26. Расстояние между двумя ближайшими друг к другу наблюдениями равно 0,31.

КЛАСТЕРНЫЙ АНАЛИЗ

Поскольку в наборе данных была высокая корреляция, я приступил к анализу PCA и продолжил работу с данными.

pca_df <- predict(data_pca)[,1:2]

k-значит

Определение количества кластеров

fviz_nbclust(pca_df , kmeans, nstart = 30, iter.max = 500, method = "wss")

ЛОКТЕВОЙ МЕТОД

Согласно методу локтя точка локтя находится на 2. Следовательно, следует выбрать 2 кластера.

fviz_nbclust(pca_df, kmeans ,method = "silhouette")

МЕТОД СИЛЬХУТТЕ

Судя по графику силуэта, наибольшее значение силуэта наблюдается для 2 кластеров. 3 очень близок к этому, так что можно попробовать оба

fviz_nbclust(pca_df, kmeans ,nstart = 25, method = "gap_stat", nboot = 500)

На графике статистики пропусков наиболее подходящим кластером является 2. Таким образом, на основе этих графиков будут опробованы кластеры 2 и 3.

set.seed(2022900087)
km_data <- kmeans(pca_df, 2, nstart=25)
print(km_data)
## K-means clustering with 2 clusters of sizes 171, 398
##
## Cluster means:
## PC1 PC2
## 1 -3.001746 0.07482399
## 2 1.289695 -0.03214799
##
## Clustering vector:
## [1] 1 1 1 1 1 1 1 1 1 1 2 1 1 2 1 1 2 1 1 2 2 2 1 1 1 1 1 1 1 1 1 2 1 1 1 1 2
## [38] 2 2 2 2 2 1 2 2 1 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 2 1 2 2 1 2 2 2 2 1 2 1 2
## [75] 2 2 2 1 1 2 2 2 1 1 2 1 2 1 2 1 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2
## [112] 2 1 2 2 2 2 1 1 2 2 1 1 2 2 2 2 1 1 1 2 1 1 2 1 2 2 2 1 2 2 2 2 2 2 2 1 2
## [149] 2 2 2 2 1 2 2 2 1 2 2 2 2 1 1 2 1 2 2 2 1 2 2 2 1 2 2 2 2 1 2 2 1 1 2 2 2
## [186] 2 2 2 2 2 1 2 2 2 1 2 1 1 1 2 2 1 1 1 2 2 2 2 2 2 1 2 1 1 1 2 2 2 1 1 2 2
## [223] 2 1 2 2 2 2 2 1 1 2 2 1 2 2 1 1 2 1 2 2 2 2 1 2 2 2 2 2 1 2 1 1 1 2 1 1 1
## [260] 1 1 2 1 2 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2
## [297] 2 2 2 2 1 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 2 2 2 1 1 1 2 2
## [334] 2 2 1 2 1 2 1 2 2 2 1 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1
## [371] 1 2 1 1 2 1 2 2 2 1 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2
## [408] 2 1 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 2 2 2 2 1 2 2
## [445] 1 2 1 2 2 1 2 1 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 1 2
## [482] 2 2 2 2 2 2 1 2 2 2 2 1 2 2 2 2 2 1 1 2 1 2 1 1 2 2 2 2 1 2 2 1 2 2 2 1 1
## [519] 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [556] 2 2 2 2 2 2 2 1 1 1 1 2 1 2
##
## Within cluster sum of squares by cluster:
## [1] 1216.540 1121.768
## (between_SS / total_SS = 48.5 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"

Согласно выходным данным, в первом кластере 171 наблюдение, во втором — 398. Это немного неуравновешенно. Всего объяснено 48,5% дисперсии. Разница между суммой квадратов внутри кластера невелика, что желательно.

fviz_cluster(km_data, data = pca_df,
ellipse.type = "convex",
star.plot = TRUE,
repel = TRUE,
ggtheme = theme_minimal())

Разложение происходит только в измерении PC1. Дисперсия красных кластеров кажется больше. Есть много близко расположенных наблюдений. При анализе с тремя кластерами число элементов в двух кластерах оказывается близким. В одном кластере больше элементов. Сумма дисперсий внутри кластеров высока, поэтому я не включил ее в отчет.

К-МЕДОИДЫ

Определение количества кластеров

fviz_nbclust(pca_df , pam, method = "wss")

ЛОКТЕВОЙ МЕТОД

Судя по этому рисунку, локоть формируется в 2 кластера. Поэтому оптимальное количество кластеров равно 2.

fviz_nbclust(pca_df , pam, method = "silhouette")

Силуэт

Согласно диаграмме силуэта, наивысшая оценка силуэта достигается для 2 кластеров, что указывает на то, что наиболее подходящее количество кластеров равно 2.

fviz_nbclust(pca_df , pam, method = "gap")

ЗАЗОР

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

set.seed(2022900087)
pam_data <- pam(pca_df,2)
print(pam_data)
## Medoids:
## ID PC1 PC2
## [1,] 499 -2.357211 0.30131315
## [2,] 269 1.358672 0.03762238
## Clustering vector:
## [1] 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 2 1 1 2 2 2 1 1 1 1 1 1 1 1 1 2 1 1 1 1 2
## [38] 2 2 2 2 2 1 2 2 1 2 1 2 2 2 2 2 1 2 2 1 1 2 2 2 2 1 2 2 1 2 2 2 2 1 2 1 2
## [75] 2 1 2 1 1 2 2 1 1 1 2 1 2 1 2 1 2 1 2 2 1 1 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2
## [112] 2 1 2 2 2 2 1 1 1 2 1 1 2 2 2 2 1 1 1 2 1 1 2 1 2 2 2 1 2 2 1 2 2 2 2 1 2
## [149] 2 2 2 2 1 2 2 2 1 2 2 2 2 1 1 2 1 2 2 1 1 2 2 2 1 2 2 2 2 1 2 2 1 1 2 2 2
## [186] 2 1 2 2 2 1 2 2 2 1 2 1 1 1 1 2 1 1 1 2 2 2 1 2 2 1 2 1 1 1 1 2 2 1 1 2 2
## [223] 2 1 2 2 2 2 2 1 1 2 2 1 2 2 1 1 2 1 2 2 2 2 1 2 2 2 2 2 1 2 1 1 1 2 1 1 1
## [260] 1 1 2 1 2 1 1 2 2 2 2 2 2 1 2 1 2 2 1 2 2 1 2 1 1 2 2 2 2 2 2 1 2 2 2 2 2
## [297] 2 2 2 2 1 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 2 2 2 1 1 1 2 2
## [334] 2 2 1 2 1 2 1 2 2 2 1 2 2 2 2 2 2 2 1 1 1 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1
## [371] 1 2 1 1 2 1 2 2 2 1 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2
## [408] 2 1 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 2 2 2 2 1 2 2
## [445] 1 2 1 2 2 1 2 1 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 1 2
## [482] 2 2 2 1 2 2 1 2 2 2 2 1 2 2 2 2 2 1 1 2 1 2 1 1 2 2 2 2 1 2 2 1 2 2 2 1 1
## [519] 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [556] 2 2 2 2 2 2 2 1 1 1 1 1 1 2
## Objective function:
## build swap
## 1.806580 1.700399
##
## Available components:
## [1] "medoids" "id.med" "clustering" "objective" "isolation"
## [6] "clusinfo" "silinfo" "diss" "call" "data"

На выходе первый кластер имеет 499 элементов, а второй кластер имеет 269 элементов. Разница кажется существенной. Визуальное представление может обеспечить лучшее понимание.

fviz_cluster(pam_data,
ellipse.type = "convex",
repel = TRUE,
ggtheme = theme_classic()
)

На графике разделение произошло только в ПК1. Дисперсия красного кластера высока. Перекрытия нет.

КЛАРА

Определение количества кластеров

fviz_nbclust(pca_df , clara, method = "wss")

ЛОКТЕВОЙ МЕТОД

Изгиб формируется во втором кластере, поэтому можно попробовать два кластера.

fviz_nbclust(pca_df , clara, method = "silhouette")

Наивысший балл за силуэт получен для второго кластера. Поэтому можно попробовать два кластера.

fviz_nbclust(pca_df , clara, method = "gap")

ЗАЗОР

Наибольшее значение статистики разрыва наблюдается для двух кластеров. Следовательно, можно протестировать два кластера.

clara_res <- clara(pca_df, 2, samples = 50, pamLike = TRUE)
print(clara_res)
## Call: clara(x = pca_df, k = 2, samples = 50, pamLike = TRUE)
## Medoids:
## PC1 PC2
## [1,] -2.274221 0.51833804
## [2,] 1.457832 -0.08131143
## Objective function: 1.703617
## Clustering vector: int [1:569] 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 2 1 ...
## Cluster sizes: 188 381
## Best sample:
## [1] 8 25 41 46 49 64 69 74 80 116 122 133 158 164 178 189 218 240 248
## [20] 249 274 279 281 282 287 300 302 322 349 370 396 409 427 430 450 491 493 507
## [39] 515 519 536 547 559 561
##
## Available components:
## [1] "sample" "medoids" "i.med" "clustering" "objective"
## [6] "clusinfo" "diss" "call" "silinfo" "data"

В первом кластере 188 наблюдений, во втором кластере 381 наблюдение.

fviz_cluster(clara_res,
ellipse.type = "convex",
geom = "point", pointsize = 1,
ggtheme = theme_classic()

Разделение произошло только в ПК1. Красный кластер имеет более высокую дисперсию и не перекрывается.

Выбор метода

Нет существенной разницы между выходными данными кластера и кластерной графикой методов. Однако было замечено, что на диаграммах набора данных есть много выбросов. Поскольку алгоритм PAM более устойчив к выбросам, был выбран алгоритм PAM.

Окончательная кластеризация и обзоры

Был добавлен набор данных объектов, содержащий информацию о кластере.

final_df <- cbind(df, cluster= pam_data$clustering )

Функциональные средства, сгруппированные по диагнозу

aggregate(df, by=list(cluster=wdbc$Diagnosis), mean)
## cluster radius texture perimeter area smoothness compactness
## 1 B 12.14652 17.91476 78.07541 462.7902 0.09247765 0.08008462
## 2 M 17.46283 21.60491 115.36538 978.3764 0.10289849 0.14518778
## concavity concave.points symmetry fractal.dimension
## 1 0.04605762 0.02571741 0.174186 0.06286739
## 2 0.16077472 0.08799000 0.192909 0.06268009

Средства признаков, сгруппированные в соответствии с результатами кластеризации

aggregate(df, by=list(cluster=pam_data$clustering), mean)
## cluster radius texture perimeter area smoothness compactness
## 1 1 17.82573 21.32258 118.08353 1016.8732 0.10443305 0.15545542
## 2 2 12.27319 18.27050 78.87734 473.4195 0.09231325 0.07871633
## concavity concave.points symmetry fractal.dimension
## 1 0.17539953 0.09442937 0.1965689 0.06361021
## 2 0.04538496 0.02610399 0.1734380 0.06239024

При сравнении двух выходных данных было определено, что 2 соответствует M, а 1 соответствует B по результатам кластеризации.

Я хотел проверить точность результатов кластеризации с помощью матрицы путаницы.

wdbc$Diagnosis <- ifelse(wdbc$Diagnosis == "M", 2, 1)
table(wdbc$Diagnosis, pam_data$clustering)
##
##    1  2
## 1 10 347
## 2 180 32

Кластеризация была выполнена с вероятностью успеха 92%.

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