Breast cancer is a disease in which cells in the breast grow out of control. There are different kinds of breast cancer. The kind of breast cancer depends on which cells in the breast turn into cancer. Breast cancer is a formidable health challenge affecting millions of women globally. Characterized by abnormal cell growth in breast tissue, early detection is paramount for effective treatment and improved outcomes. Breast cancer can spread outside the breast through blood vessels and lymph vessels. When breast cancer spreads to other parts of the body, it is said to have metastasized.
In this LBB we will make an unsupervised learning model to find the patterns in our data to generate information.
library(dplyr)
library(FactoMineR)
## Warning: package 'FactoMineR' was built under R version 4.3.3
library(factoextra)
## Warning: package 'factoextra' was built under R version 4.3.3
## Warning: package 'ggplot2' was built under R version 4.3.3
options(scipen = 999)
cancer <- read.csv("data_input/data.csv")
glimpse(cancer)
## Rows: 569
## Columns: 33
## $ id <int> 842302, 842517, 84300903, 84348301, 84358402, …
## $ diagnosis <chr> "M", "M", "M", "M", "M", "M", "M", "M", "M", "…
## $ radius_mean <dbl> 17.990, 20.570, 19.690, 11.420, 20.290, 12.450…
## $ texture_mean <dbl> 10.38, 17.77, 21.25, 20.38, 14.34, 15.70, 19.9…
## $ perimeter_mean <dbl> 122.80, 132.90, 130.00, 77.58, 135.10, 82.57, …
## $ area_mean <dbl> 1001.0, 1326.0, 1203.0, 386.1, 1297.0, 477.1, …
## $ smoothness_mean <dbl> 0.11840, 0.08474, 0.10960, 0.14250, 0.10030, 0…
## $ compactness_mean <dbl> 0.27760, 0.07864, 0.15990, 0.28390, 0.13280, 0…
## $ concavity_mean <dbl> 0.30010, 0.08690, 0.19740, 0.24140, 0.19800, 0…
## $ concave.points_mean <dbl> 0.14710, 0.07017, 0.12790, 0.10520, 0.10430, 0…
## $ symmetry_mean <dbl> 0.2419, 0.1812, 0.2069, 0.2597, 0.1809, 0.2087…
## $ fractal_dimension_mean <dbl> 0.07871, 0.05667, 0.05999, 0.09744, 0.05883, 0…
## $ radius_se <dbl> 1.0950, 0.5435, 0.7456, 0.4956, 0.7572, 0.3345…
## $ texture_se <dbl> 0.9053, 0.7339, 0.7869, 1.1560, 0.7813, 0.8902…
## $ perimeter_se <dbl> 8.589, 3.398, 4.585, 3.445, 5.438, 2.217, 3.18…
## $ area_se <dbl> 153.40, 74.08, 94.03, 27.23, 94.44, 27.19, 53.…
## $ smoothness_se <dbl> 0.006399, 0.005225, 0.006150, 0.009110, 0.0114…
## $ compactness_se <dbl> 0.049040, 0.013080, 0.040060, 0.074580, 0.0246…
## $ concavity_se <dbl> 0.05373, 0.01860, 0.03832, 0.05661, 0.05688, 0…
## $ concave.points_se <dbl> 0.015870, 0.013400, 0.020580, 0.018670, 0.0188…
## $ symmetry_se <dbl> 0.03003, 0.01389, 0.02250, 0.05963, 0.01756, 0…
## $ fractal_dimension_se <dbl> 0.006193, 0.003532, 0.004571, 0.009208, 0.0051…
## $ radius_worst <dbl> 25.38, 24.99, 23.57, 14.91, 22.54, 15.47, 22.8…
## $ texture_worst <dbl> 17.33, 23.41, 25.53, 26.50, 16.67, 23.75, 27.6…
## $ perimeter_worst <dbl> 184.60, 158.80, 152.50, 98.87, 152.20, 103.40,…
## $ area_worst <dbl> 2019.0, 1956.0, 1709.0, 567.7, 1575.0, 741.6, …
## $ smoothness_worst <dbl> 0.1622, 0.1238, 0.1444, 0.2098, 0.1374, 0.1791…
## $ compactness_worst <dbl> 0.6656, 0.1866, 0.4245, 0.8663, 0.2050, 0.5249…
## $ concavity_worst <dbl> 0.71190, 0.24160, 0.45040, 0.68690, 0.40000, 0…
## $ concave.points_worst <dbl> 0.26540, 0.18600, 0.24300, 0.25750, 0.16250, 0…
## $ symmetry_worst <dbl> 0.4601, 0.2750, 0.3613, 0.6638, 0.2364, 0.3985…
## $ fractal_dimension_worst <dbl> 0.11890, 0.08902, 0.08758, 0.17300, 0.07678, 0…
## $ X <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
In this case we will use only the mean data. Therefore we will remove
SE and Worst data. Also we want to change diagnosis type
into factor.
cancer_clean <- cancer %>%
select(-c(1, 13:33)) %>%
mutate(diagnosis = as.factor(diagnosis))
glimpse(cancer_clean)
## Rows: 569
## Columns: 11
## $ diagnosis <fct> M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M,…
## $ radius_mean <dbl> 17.990, 20.570, 19.690, 11.420, 20.290, 12.450,…
## $ texture_mean <dbl> 10.38, 17.77, 21.25, 20.38, 14.34, 15.70, 19.98…
## $ perimeter_mean <dbl> 122.80, 132.90, 130.00, 77.58, 135.10, 82.57, 1…
## $ area_mean <dbl> 1001.0, 1326.0, 1203.0, 386.1, 1297.0, 477.1, 1…
## $ smoothness_mean <dbl> 0.11840, 0.08474, 0.10960, 0.14250, 0.10030, 0.…
## $ compactness_mean <dbl> 0.27760, 0.07864, 0.15990, 0.28390, 0.13280, 0.…
## $ concavity_mean <dbl> 0.30010, 0.08690, 0.19740, 0.24140, 0.19800, 0.…
## $ concave.points_mean <dbl> 0.14710, 0.07017, 0.12790, 0.10520, 0.10430, 0.…
## $ symmetry_mean <dbl> 0.2419, 0.1812, 0.2069, 0.2597, 0.1809, 0.2087,…
## $ fractal_dimension_mean <dbl> 0.07871, 0.05667, 0.05999, 0.09744, 0.05883, 0.…
Data is cleaned. From glimpse function above we can see
there are 569 rows with 11 columns.
All the columns are:
diagnosis : The diagnosis of breast tissue samples,
where ‘M’ indicates malignant (cancerous) and ‘B’ indicates benign
(non-cancerous)radius_mean : Radius of the nucleus of the cellstexture_mean : Texture of the cellsperimeter_mean : perimeter of the cellsarea_mean : area of the cellssmoothness_mean : Smoothness (local variation in radius
lengths) of the cellscompactness_mean : Compactnessconcavity_mean : Severity of concave portions of the
contourconcave.points_mean : Number of concave portions of the
contoursymmetry_mean : Symmetry of the cellsfractal_dimension_mean : Fractal dimensionNext we will check is there any missing value in the data before we start modeling.
colSums(is.na(cancer_clean))
## diagnosis radius_mean texture_mean
## 0 0 0
## perimeter_mean area_mean smoothness_mean
## 0 0 0
## compactness_mean concavity_mean concave.points_mean
## 0 0 0
## symmetry_mean fractal_dimension_mean
## 0 0
There is no missing value in the data.
Before creating the Unsupervised Learning model, we need create an index to identify which column is categorical and which one is numeric
qualivar <- c(1)
quantivar <- c(2:11)
Next we will create the model.
cancer_pca <- PCA(X = cancer_clean,
scale.unit = T,
quali.sup = qualivar,
graph = F,
ncp = 10)
scale.unit = T means that our data is automatically
scaled. Scaling is used before PCA because we want the data to be at the
same scale.
quali.sup = qualivar means we give our
model information which column index are categorical so that our model
will ignore and only use numerical variables only.
ncp = 10 means that we will use all 10 of our numeric
variables as our PC.
We will check our eigen value of our model that we just created.
cancer_pca$eig
## eigenvalue percentage of variance cumulative percentage of variance
## comp 1 5.4785879917 54.785879917 54.78588
## comp 2 2.5187135854 25.187135854 79.97302
## comp 3 0.8806151792 8.806151792 88.77917
## comp 4 0.4990094357 4.990094357 93.76926
## comp 5 0.3725391897 3.725391897 97.49465
## comp 6 0.1241417485 1.241417485 98.73607
## comp 7 0.0800853104 0.800853104 99.53692
## comp 8 0.0348897928 0.348897928 99.88582
## comp 9 0.0111354606 0.111354606 99.99718
## comp 10 0.0002823059 0.002823059 100.00000
We want to use as few PC as possible while retaining as much data as we can. In this case, we want to retain at least 90% of our data, which in our model, we will choose PC1 - PC4 from 10 PC. By doing so, we could reduce our dimension by 60% while also retaining 93.77% of our data.
pca_keep <- as.data.frame(cancer_pca$ind$coord[, 1:4])
pca_keep_1 <- cbind(pca_keep,
Type = cancer_clean$diagnosis)
pca_keep_1
plot.PCA(x= cancer_pca,
choix = "ind",
habillage = "area_mean",
select = "contrib 10",
invinsible = "quali")
Based on our Individual Factor Map above, there are some data which are
an outlier. The top 10 of the data are data number 505, 4, 79, 109, 123,
83, 353, 181, 462, 213.
plot.PCA(x = cancer_pca,
choix = "var")
fviz_contrib(X = cancer_pca,
choice = "var",
axes = 1)
fviz_contrib(X = cancer_pca,
choice = "var",
axes = 2)
Insights that we get from our plots are:
concave.points,
concavity, perimeter, compacness,
area, and radiusfractal_dimension,
smoothness, and symmetrytextureClustering is a method of grouping the data based on their characteristics. First we will check our data’s summary
summary(cancer_clean)
## diagnosis radius_mean texture_mean perimeter_mean area_mean
## B:357 Min. : 6.981 Min. : 9.71 Min. : 43.79 Min. : 143.5
## M:212 1st Qu.:11.700 1st Qu.:16.17 1st Qu.: 75.17 1st Qu.: 420.3
## Median :13.370 Median :18.84 Median : 86.24 Median : 551.1
## Mean :14.127 Mean :19.29 Mean : 91.97 Mean : 654.9
## 3rd Qu.:15.780 3rd Qu.:21.80 3rd Qu.:104.10 3rd Qu.: 782.7
## Max. :28.110 Max. :39.28 Max. :188.50 Max. :2501.0
## smoothness_mean compactness_mean concavity_mean concave.points_mean
## Min. :0.05263 Min. :0.01938 Min. :0.00000 Min. :0.00000
## 1st Qu.:0.08637 1st Qu.:0.06492 1st Qu.:0.02956 1st Qu.:0.02031
## Median :0.09587 Median :0.09263 Median :0.06154 Median :0.03350
## Mean :0.09636 Mean :0.10434 Mean :0.08880 Mean :0.04892
## 3rd Qu.:0.10530 3rd Qu.:0.13040 3rd Qu.:0.13070 3rd Qu.:0.07400
## Max. :0.16340 Max. :0.34540 Max. :0.42680 Max. :0.20120
## symmetry_mean fractal_dimension_mean
## Min. :0.1060 Min. :0.04996
## 1st Qu.:0.1619 1st Qu.:0.05770
## Median :0.1792 Median :0.06154
## Mean :0.1812 Mean :0.06280
## 3rd Qu.:0.1957 3rd Qu.:0.06612
## Max. :0.3040 Max. :0.09744
Based on the summary above, the data scale is pretty wide. In order to do clustering, we need a equally balanced data. So we will scale our data and remove factor column because we cannot determine our optimum k if there’s still a factor column.
cancer_scale <- scale(cancer_clean[, -1])
Then we will check our k optimum
fviz_nbclust(
x = cancer_scale,
FUNcluster = kmeans,
method = "wss"
)
From plot above, our k optimum is 2.
Next we will create our cluster model with our k optimum.
cancer_cluster <- kmeans(cancer_scale,
centers = 2)
cancer_cluster
## K-means clustering with 2 clusters of sizes 396, 173
##
## Cluster means:
## radius_mean texture_mean perimeter_mean area_mean smoothness_mean
## 1 -0.4926965 -0.2197678 -0.5050319 -0.4868855 -0.2641564
## 2 1.1277909 0.5030524 1.1560268 1.1144893 0.6046586
## compactness_mean concavity_mean concave.points_mean symmetry_mean
## 1 -0.4524743 -0.5124564 -0.549105 -0.2600021
## 2 1.0357214 1.1730216 1.256911 0.5951494
## fractal_dimension_mean
## 1 -0.0527427
## 2 0.1207289
##
## Clustering vector:
## [1] 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 2 1 1 1 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1
## [38] 1 1 1 1 1 2 1 1 2 1 1 1 1 1 1 1 2 1 1 2 2 1 1 1 1 2 1 1 2 1 1 1 1 2 1 2 1
## [75] 1 1 1 2 2 1 1 1 2 2 1 2 1 2 1 2 1 1 1 1 2 2 1 1 1 1 1 1 1 1 1 2 1 1 2 1 1
## [112] 1 2 1 1 1 1 2 2 2 1 2 2 1 1 1 1 2 2 2 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 2 1
## [149] 1 1 1 1 2 1 1 1 2 1 1 1 1 2 2 1 2 1 1 1 2 1 1 1 2 1 1 1 1 2 1 1 2 2 1 1 1
## [186] 1 2 1 1 1 2 1 1 1 2 1 2 2 2 1 1 2 2 2 1 1 1 1 1 1 2 1 2 2 2 1 1 1 2 2 1 1
## [223] 1 2 1 1 1 1 1 2 2 1 1 2 1 1 2 2 1 2 1 1 1 1 2 1 1 1 1 1 2 1 2 2 2 1 2 2 2
## [260] 2 2 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 1 2 1 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1
## [297] 1 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 2 1 2 1 1 1 1 2 2 2 1 1
## [334] 1 1 2 1 2 1 2 1 1 1 2 1 1 1 1 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 2 2
## [371] 2 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 2 2 1 1 1 1 1 1 2 1 1 1 1 1 1
## [408] 1 2 1 1 1 1 1 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 2 1 2 2 1 1 1 1 1 1 1 2 1 1
## [445] 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 1 2 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 2 1
## [482] 1 1 1 1 1 1 2 1 1 1 1 2 1 1 1 1 1 2 2 1 2 1 2 1 1 1 1 1 2 1 1 2 1 1 1 2 2
## [519] 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [556] 1 1 1 1 1 1 1 2 2 2 2 1 2 1
##
## Within cluster sum of squares by cluster:
## [1] 1918.436 1557.576
## (between_SS / total_SS = 38.8 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"
Next we will evaluate our new cluster model
cancer_cluster$withinss
## [1] 1918.436 1557.576
cancer_cluster$betweenss/cancer_cluster$totss
## [1] 0.388026
Based on the result above, our cluster model isn’t that good in classifying our data because our within sum of square (wss) is pretty high with 1918.436 for our first cluster and 1557.576 for our second cluster. Our between sum of square (bss) and total sum of square (tss) is also pretty low with 0.388 point. This could happen because we only create 2 cluster. Therefor it’s the best to use classification method in our case