עד כה בקורס עסקנו בקשר שבין משתנים מסבירים (\(X_1,\ldots,X_p\)) לבין משתנה תלוי \(y\), ואיך מייצרים מודלים שונים שמתארים את הקשר שביניהם (בין אם מודלי רגרסיה, או מודלים מתקדמים יותר).
לעיתים הבעיה הניצבת בפנינו כחוקרים היא לא לתאר קשר בין משתנה תלוי למשתנים בלתי תלויים, אלא ללמוד על מבני הנתונים מתוך משתנים בלתי תלויים. לדוגמה:
בגנטיקה של אוכלוסיות לדוגמה, עוסקים בדיוק בבעיות כאלו: כיצד לסווג מינים שונים או כיצד להבין ממחקר גנטי על הקשר ההיסטורי שבין אוכלוסיות שונות. במקרה הבא, הגדרה של שני משתנים בלבד (PC1, PC2) מצליחה להפריד חלק מהאוכלוסיות באופן טוב, שדי מזכיר את מפת אירופה. https://stats.stackexchange.com/questions/8777/in-genome-wide-association-studies-what-are-principal-components
המפה מתארת איך ממגוון משתנים המתארים שינויים גנטיים, ניתן לחלץ שני משתנים בלבד המסבירים את מירב השונות בין אנשים שונים, ואת הדימיון הרב המתקבל בין משתנים אלו לבין מפת הפיזור של האנשים באירופה.
המינים הבאים סווגו לפי מידת הקרבה שלהן אחד לשני, בתרשים שנקרא Dendrogram. התרשים מסודר כעץ שבו ענפים כאשר ענפים סמוכים הם תצפיות שיש ביניהן דמיון. https://www.researchgate.net/figure/Dendrogram-showing-the-genetic-diversity-of-the-genomic-selection-training-population_fig2_317632929
סוג הניתוחים הללו רלוונטי למקרים בהם אנחנו מנסים לפענח כיצד פרטים שונים מתקבצים יחדיו באוכלוסיה (Clustering) או כיצד משתנים שונים “מתנהגים” בהשוואה אחד לשני (Principle Component Analysis).
שימו לב שיש הבדל מהותי בין יצירת אשכולות - המתייחס לפרטים שונים באוכלוסיה (תצפיות) לבין ניתוח גורמים (המתייחס למשתנים עצמם).
הרבה פעמים נשתמש בכלים אלו של unsupervised learning, כשלב ביניים לפני שנעבור למידול supervised.
נדון ראשית בניתוח גורמים (Principle Component Analysis - PCA).
בניתוח מסוג PCA, אנחנו משתמשים בכלים של אלגברה לינארית כדי לסובב ולהזיז את מערכת הצירים של הנתונים. הזזה זו מתבצעת באופן כזה, שבו מערכת הצירים החדשה היא מערכת צירים שבה הציר הראשון הוא בעל השונות הגבוהה ביותר, הציר השני בעל שונות פחות גבוהה וכן הלאה (הכוונה לפיזור הנתונים בכל ציר חדש).
אם אנחנו בוחרים תת-קבוצה של צירים אלו, המשמעות היא שאנחנו בוחרים תת-קבוצה שמסבירה “X% מהשונות שיש בנתונים”.
library(tidyverse)
## -- Attaching packages --------------------------------------------------------------------- tidyverse 1.2.1 --
## <U+221A> ggplot2 3.0.0 <U+221A> purrr 0.2.5
## <U+221A> tibble 1.4.2 <U+221A> dplyr 0.7.6
## <U+221A> tidyr 0.8.1 <U+221A> stringr 1.2.0
## <U+221A> readr 1.1.1 <U+221A> forcats 0.2.0
## -- Conflicts ------------------------------------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
# lets try to reduce the dimension of the iris dataset
ggplot(iris, aes(Sepal.Length, Sepal.Width, color = Species)) + geom_point()
ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) + geom_point()
ggplot(iris, aes(Sepal.Length, Petal.Width, color = Species)) + geom_point()
ggplot(iris, aes(Sepal.Width, Petal.Width, color = Species)) + geom_point()
ggplot(iris, aes(Sepal.Width, Petal.Length, color = Species)) + geom_point()
ggplot(iris, aes(Petal.Length, Petal.Width, color = Species)) + geom_point()
# It looks like every two axis have their interaction (or not)
# Some are very correlated, for example the Petal.Width and Petal.Length seem to have a very strong linear relationship.
# To a lesser extent, the same can be said for Petal.Length<->Sepal.Length, and Petal.Width<->Sepal.Length
# Now, lets run the PCA
iris_pca <- prcomp(iris %>% select(-Species))
iris_pca
## Standard deviations (1, .., p=4):
## [1] 2.0562689 0.4926162 0.2796596 0.1543862
##
## Rotation (n x k) = (4 x 4):
## PC1 PC2 PC3 PC4
## Sepal.Length 0.36138659 -0.65658877 0.58202985 0.3154872
## Sepal.Width -0.08452251 -0.73016143 -0.59791083 -0.3197231
## Petal.Length 0.85667061 0.17337266 -0.07623608 -0.4798390
## Petal.Width 0.35828920 0.07548102 -0.54583143 0.7536574
הפקודה מדווחת לנו על ארבעה רכיבים (תמיד מספר הרכיבים יהיה כמספר המשתנים הכללי שהכנסנו, במקרה זה ארבע משתנים).
כל משתנה מקבל “מקדם” שהוא המקדם שבו צריך להכפיל את המשתנה בשביל לקבל את ערך הרכיב החדש, הסכום שלהם הוא הרכיב החדש. לפעמים ניתן לתת פרשנות לרכיב החדש (כמעין ממוצע משוקלל), ולפעמים לא. הרבה פעמים התוצר של PCA הוא פשוט “קופסה שחורה”.
כאשר משתמשים בפקודת summary
על אובייקט PCA, מקבלים את השונות של כל משתנה חדש, ואת שיעור השונות המוסברת (שלו והמצטברת).
summary(iris_pca)
## Importance of components%s:
## PC1 PC2 PC3 PC4
## Standard deviation 2.0563 0.49262 0.2797 0.15439
## Proportion of Variance 0.9246 0.05307 0.0171 0.00521
## Cumulative Proportion 0.9246 0.97769 0.9948 1.00000
# the following matrix contains the variables after they were rotated by the PCA
head(iris_pca$x)
## PC1 PC2 PC3 PC4
## [1,] -2.684126 -0.3193972 0.02791483 0.002262437
## [2,] -2.714142 0.1770012 0.21046427 0.099026550
## [3,] -2.888991 0.1449494 -0.01790026 0.019968390
## [4,] -2.745343 0.3182990 -0.03155937 -0.075575817
## [5,] -2.728717 -0.3267545 -0.09007924 -0.061258593
## [6,] -2.280860 -0.7413304 -0.16867766 -0.024200858
# to rotate new data, just use the standard predict form
predict(object = iris_pca, newdata = iris %>% slice(1:5))
## Warning: package 'bindrcpp' was built under R version 3.4.4
## PC1 PC2 PC3 PC4
## [1,] -2.684126 -0.3193972 0.02791483 0.002262437
## [2,] -2.714142 0.1770012 0.21046427 0.099026550
## [3,] -2.888991 0.1449494 -0.01790026 0.019968390
## [4,] -2.745343 0.3182990 -0.03155937 -0.075575817
## [5,] -2.728717 -0.3267545 -0.09007924 -0.061258593
# `slice` selects the rows 1:5
ggplot(as_tibble(iris_pca$x) %>%
mutate(Species = iris$Species), aes(x = PC1, y = PC2, color = Species)) +
geom_point() +
coord_equal() +
ggtitle("The first two components of PCA on the iris dataset")
שימו לב לטווחים של ציר ה-PC1 לעומת הטווחים של ציר ה-PC2.
לעיתים, שלב ה-PCA מהווה שלב מקדים בשביל לבנות רגרסיה, והמשתנים המסבירים ברגרסיה הופכים להיות חלק מה-PCs.
באפשרותכם להיעזר בקוד הבא:
appointments <- read_csv("data-files/Medical_Appointments_No_Shows_KaggleV2-May-2016.csv") %>%
mutate(no_show = `No-show` == "Yes")
appointments_pca_all <- prcomp(appointments %>%
select(XXX),
XXX = XXX, XXX = XXX)
summary(appointments_pca_all)
# Add the results of PCA as new variables into a dataset
appointments_dataset_pca <- appointments %>%
bind_cols(as_tibble(appointments_pca_all$x))
# Try various options of # of PCs. When can you say that a smaller number of variables achieves similar results to using the full 7 variables?
appointments_pcaX_glm <- glm(formula =
no_show ~ PC1 + PC2 + ... + PCX,
family = binomial,
data = appointments_dataset_pca %>% filter(is_train))
# To examine performance you can either look at the residuals or visualize using an ROC...
עד כה עסקנו בטיפול במשתנים, כעת נעסוק בטיפול בתצפיות באמצעות חלוקה לאשכולות (clustering).
פקודת kmeans
מחלקת את הנקודות במרחב לפי המרחק אחת מהשניה. במובן זה היא מזכירה את knn
(שגם משתמשת במרחק בין נקודות), אך היא אינה נותנת תחזית או מתייחסת למשתנה תלוי כלשהו.
איך עובדת KMeans?
השיטה מנסה למצוא קבוצות אשר השונות בתוכן היא מינימלית (התצפיות בכל קבוצה דומות זו לזו), והשונות בין הקבוצות גבוהה (הקבוצות נמצאות רחוק אחת מהשניה).
נוסחה מקובלת לKMeans עושה שימוש במרחק אוקלידי בין הנקודות בכל קבוצה:
\[ W(C_k)=\frac{1}{|C_k|}\sum_{i,i'\in C_k}\sum_{j=1}^p(x_{ij}-x_{i'j})^2 \]
כאשר \(C_k\) הוא מספר התצפיות בקבוצה \(k\). נוסחה זו מייצגת את השונות בתוך אשכול \(k\).
פונקציית המטרה שלנו תהיה למצוא חלוקה לאשכולות \(C_1,\ldots,C_K\) כך שתקטין את סך השונות:
\[ \min_{C_1,\ldots,C_k}\sum_{k=1}^K{W(C_k)} \]
מי קובע את \(K\)? אתם.
איך? שאלה טובה.
לפעמים זה ניסוי וטעיה, לפעמים זה נגזר מדרישות או מטרות העבודה.
איך עובד האלגוריתם למציאת החלוקה \(C_1,\ldots, C_k\)?
# The original split of iris:
ggplot(iris, aes(Sepal.Width, Petal.Length, color = Species)) + geom_point()
# Now, illustrating KMeans on the two variables
iris_kmeans2 <- kmeans(iris %>% select(Sepal.Width, Petal.Length),
centers = 2)
iris_kmeans2
## K-means clustering with 2 clusters of sizes 51, 99
##
## Cluster means:
## Sepal.Width Petal.Length
## 1 3.409804 1.492157
## 2 2.875758 4.925253
##
## Clustering vector:
## [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [36] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [71] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2
## [106] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [141] 2 2 2 2 2 2 2 2 2 2
##
## Within cluster sum of squares by cluster:
## [1] 11.68196 74.62869
## (between_SS / total_SS = 82.5 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss"
## [5] "tot.withinss" "betweenss" "size" "iter"
## [9] "ifault"
iris_kmeans2$centers
## Sepal.Width Petal.Length
## 1 3.409804 1.492157
## 2 2.875758 4.925253
glimpse(iris_kmeans2)
## List of 9
## $ cluster : int [1:150] 1 1 1 1 1 1 1 1 1 1 ...
## $ centers : num [1:2, 1:2] 3.41 2.88 1.49 4.93
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : chr [1:2] "1" "2"
## .. ..$ : chr [1:2] "Sepal.Width" "Petal.Length"
## $ totss : num 493
## $ withinss : num [1:2] 11.7 74.6
## $ tot.withinss: num 86.3
## $ betweenss : num 406
## $ size : int [1:2] 51 99
## $ iter : int 1
## $ ifault : int 0
## - attr(*, "class")= chr "kmeans"
iris_kmeans3 <- kmeans(iris %>% select(Sepal.Width, Petal.Length),
centers = 3)
iris_kmeans5 <- kmeans(iris %>% select(Sepal.Width, Petal.Length),
centers = 5)
iris_kmeans <- iris %>%
mutate(kmeans2 = iris_kmeans2$cluster,
kmeans3 = iris_kmeans3$cluster,
kmeans5 = iris_kmeans5$cluster) %>%
select(starts_with("kmeans"), Sepal.Width, Petal.Length) %>%
gather(clusters, cluster_num, -Sepal.Width, -Petal.Length)
iris_kmeans_centers <- as_tibble(iris_kmeans2$centers) %>%
rownames_to_column() %>%
mutate(clusters = "kmeans2") %>%
bind_rows(
as_tibble(iris_kmeans3$centers) %>%
rownames_to_column() %>%
mutate(clusters = "kmeans3")
) %>%
bind_rows(
as_tibble(iris_kmeans5$centers) %>%
rownames_to_column() %>%
mutate(clusters = "kmeans5")
) %>%
rename(cluster_num = rowname)
ggplot(iris_kmeans, aes(x = Sepal.Width, y = Petal.Length, color = factor(cluster_num))) +
geom_point(size = 2) +
facet_wrap(~ clusters) +
guides(color = guide_legend(title = "Cluster classification")) +
geom_point(data = iris_kmeans_centers, size = 5, shape = 21,
aes(fill = factor(cluster_num)), color = "black", alpha = 0.5) +
scale_fill_discrete(guide = "none")
# and here is the original, just for comparison
ggplot(iris, aes(Sepal.Length, Sepal.Width, color = Species)) + geom_point()
kmeans
כדי לבנות קבוצות שונות של מטופלים בקובץ המטופלים. לשם כך השתמש במשתני ה-0-1 לא כולל ה-no-show. בחנו מספר אפשרויות שונות לערכי k.כדי לבחון את התפלגות הפרמטרים, באפשרותכם להיעזר בקוד הבא:
appointments_kmeansXXX <- kmeans(appointments %>% select(Scholarship:SMS_received), centers = XXX)
appointments_cluster <- appointments %>%
mutate(kmeansXXX_cluster = XXX) %>%
mutate(male = XXX == XXX)
# The following code will help you show the averages of the different variables,
# by using the mechanism we talked about in previous units (summarize_at):
appointments_cluster %>%
select(Scholarship:SMS_received, kmeansXXX_cluster, Age, male, no_show) %>%
add_count(kmeansXXX_cluster) %>%
group_by(kmeansXXX_cluster) %>%
summarize_at(.vars = vars(1:6, Age, male, n, no_show, -kmeansXXX_cluster),
.funs = funs(mean(.)))
שיטה זו משתמשת בעקרונות שונים משיטת KMeans clustering. במקום לחפש “מרכזי מסה”, ואז לסווג אילו תצפיות שייכות לכל מרכז מסה, השיטה ההירארכית מחפשת בכל נקודה אילו תצפיות “למזג” אחת לשניה לקבוצה אחת.
האלגוריתם המתואר פועל בשיטת bottom-up (מתחיל מהתצפית הבודדת). ישנם אלגוריתמים הפועלים בשיטה הפוכה (פיצול).
בהתייחס לשלב 2b באלגוריתם, ישנן פונקציות מרחק שונות. בדומה ל-KMeans אפשר להשתמש במרחק בין נקודות מרכז מסה (centroid), אך אפשר גם להשתמש במרחק בין שתי הנקודות הקרובות ביותר (single linkage), במרחק הממוצע (average linkage), ובמרחק מירבי (complete linkage).
# prepare the dataset with observation numbering
iris_prep <- iris %>%
mutate(obs = paste0(seq_along(Species), "-", Species)) %>%
column_to_rownames("obs") %>%
select(-Species)
# compute the distance matrix
iris_dist <- dist(iris_prep, method = "euclidean")
# generate the h-clustering
iris_clust <- hclust(iris_dist, method = "complete")
# We can generate the default plot which shows the tree
plot(iris_clust)
# The following will show us the order in which observations were merged:
iris_clust$order
## [1] 108 131 103 126 130 119 106 123 118 132 110 136 141 145 125 121 144
## [18] 101 137 149 116 111 148 113 140 142 146 109 104 117 138 105 129 133
## [35] 150 71 128 139 115 122 114 102 143 135 112 147 124 127 73 84 134
## [52] 120 69 88 66 76 77 55 59 78 87 51 53 86 52 57 75 98
## [69] 74 79 64 92 61 99 58 94 107 67 85 56 91 62 72 68 83
## [86] 93 95 100 89 96 97 63 65 80 60 54 90 70 81 82 42 30
## [103] 31 26 10 35 13 2 46 36 5 38 28 29 41 1 18 50 8
## [120] 40 23 7 43 3 4 48 14 9 39 17 33 34 15 16 6 19
## [137] 21 32 37 11 49 45 47 20 22 44 24 27 12 25
# The height object shows us a measure for the dissimilarity between the merged clusters
iris_clust$height
## [1] 0.0000000 0.1000000 0.1000000 0.1000000 0.1000000 0.1000000 0.1414214
## [8] 0.1414214 0.1414214 0.1414214 0.1414214 0.1414214 0.1414214 0.1414214
## [15] 0.1414214 0.1414214 0.1414214 0.1414214 0.1414214 0.1414214 0.1414214
## [22] 0.1732051 0.1732051 0.1732051 0.1732051 0.1732051 0.1732051 0.2000000
## [29] 0.2000000 0.2000000 0.2000000 0.2000000 0.2000000 0.2236068 0.2236068
## [36] 0.2449490 0.2449490 0.2449490 0.2449490 0.2449490 0.2449490 0.2449490
## [43] 0.2449490 0.2645751 0.2645751 0.2645751 0.2645751 0.2645751 0.2645751
## [50] 0.2645751 0.2645751 0.2645751 0.2828427 0.2828427 0.3000000 0.3000000
## [57] 0.3000000 0.3000000 0.3000000 0.3162278 0.3162278 0.3162278 0.3316625
## [64] 0.3316625 0.3316625 0.3316625 0.3316625 0.3316625 0.3464102 0.3464102
## [71] 0.3464102 0.3464102 0.3605551 0.3605551 0.3741657 0.3741657 0.3741657
## [78] 0.3872983 0.3872983 0.3872983 0.4000000 0.4000000 0.4123106 0.4123106
## [85] 0.4242641 0.4242641 0.4358899 0.4472136 0.4472136 0.4582576 0.4582576
## [92] 0.4690416 0.4690416 0.4690416 0.5099020 0.5196152 0.5196152 0.5196152
## [99] 0.5196152 0.5196152 0.5477226 0.5477226 0.5477226 0.5567764 0.5567764
## [106] 0.5567764 0.6000000 0.6082763 0.6082763 0.6164414 0.6164414 0.6480741
## [113] 0.6480741 0.6557439 0.6782330 0.6855655 0.7071068 0.7211103 0.7348469
## [120] 0.7549834 0.7615773 0.7874008 0.8062258 0.8062258 0.8306624 0.9055385
## [127] 0.9219544 1.0049876 1.0099505 1.0295630 1.0677078 1.0677078 1.1090537
## [134] 1.1747340 1.2124356 1.2247449 1.3892444 1.4071247 1.4177447 1.4491377
## [141] 1.4525839 1.4628739 1.6613248 1.7058722 2.2360680 2.4289916 3.2109189
## [148] 4.0249224 7.0851958
# We can even cut the tree at a specific height or a specific number of clusters
cutree(iris_clust, k = 3)
## 1-setosa 2-setosa 3-setosa 4-setosa 5-setosa
## 1 1 1 1 1
## 6-setosa 7-setosa 8-setosa 9-setosa 10-setosa
## 1 1 1 1 1
## 11-setosa 12-setosa 13-setosa 14-setosa 15-setosa
## 1 1 1 1 1
## 16-setosa 17-setosa 18-setosa 19-setosa 20-setosa
## 1 1 1 1 1
## 21-setosa 22-setosa 23-setosa 24-setosa 25-setosa
## 1 1 1 1 1
## 26-setosa 27-setosa 28-setosa 29-setosa 30-setosa
## 1 1 1 1 1
## 31-setosa 32-setosa 33-setosa 34-setosa 35-setosa
## 1 1 1 1 1
## 36-setosa 37-setosa 38-setosa 39-setosa 40-setosa
## 1 1 1 1 1
## 41-setosa 42-setosa 43-setosa 44-setosa 45-setosa
## 1 1 1 1 1
## 46-setosa 47-setosa 48-setosa 49-setosa 50-setosa
## 1 1 1 1 1
## 51-versicolor 52-versicolor 53-versicolor 54-versicolor 55-versicolor
## 2 2 2 3 2
## 56-versicolor 57-versicolor 58-versicolor 59-versicolor 60-versicolor
## 3 2 3 2 3
## 61-versicolor 62-versicolor 63-versicolor 64-versicolor 65-versicolor
## 3 3 3 2 3
## 66-versicolor 67-versicolor 68-versicolor 69-versicolor 70-versicolor
## 2 3 3 2 3
## 71-versicolor 72-versicolor 73-versicolor 74-versicolor 75-versicolor
## 2 3 2 2 2
## 76-versicolor 77-versicolor 78-versicolor 79-versicolor 80-versicolor
## 2 2 2 2 3
## 81-versicolor 82-versicolor 83-versicolor 84-versicolor 85-versicolor
## 3 3 3 2 3
## 86-versicolor 87-versicolor 88-versicolor 89-versicolor 90-versicolor
## 2 2 2 3 3
## 91-versicolor 92-versicolor 93-versicolor 94-versicolor 95-versicolor
## 3 2 3 3 3
## 96-versicolor 97-versicolor 98-versicolor 99-versicolor 100-versicolor
## 3 3 2 3 3
## 101-virginica 102-virginica 103-virginica 104-virginica 105-virginica
## 2 2 2 2 2
## 106-virginica 107-virginica 108-virginica 109-virginica 110-virginica
## 2 3 2 2 2
## 111-virginica 112-virginica 113-virginica 114-virginica 115-virginica
## 2 2 2 2 2
## 116-virginica 117-virginica 118-virginica 119-virginica 120-virginica
## 2 2 2 2 2
## 121-virginica 122-virginica 123-virginica 124-virginica 125-virginica
## 2 2 2 2 2
## 126-virginica 127-virginica 128-virginica 129-virginica 130-virginica
## 2 2 2 2 2
## 131-virginica 132-virginica 133-virginica 134-virginica 135-virginica
## 2 2 2 2 2
## 136-virginica 137-virginica 138-virginica 139-virginica 140-virginica
## 2 2 2 2 2
## 141-virginica 142-virginica 143-virginica 144-virginica 145-virginica
## 2 2 2 2 2
## 146-virginica 147-virginica 148-virginica 149-virginica 150-virginica
## 2 2 2 2 2
cutree(iris_clust, h = 1)
## 1-setosa 2-setosa 3-setosa 4-setosa 5-setosa
## 1 1 2 2 1
## 6-setosa 7-setosa 8-setosa 9-setosa 10-setosa
## 3 2 1 2 1
## 11-setosa 12-setosa 13-setosa 14-setosa 15-setosa
## 3 4 1 2 5
## 16-setosa 17-setosa 18-setosa 19-setosa 20-setosa
## 5 5 1 3 4
## 21-setosa 22-setosa 23-setosa 24-setosa 25-setosa
## 3 4 2 4 4
## 26-setosa 27-setosa 28-setosa 29-setosa 30-setosa
## 1 4 1 1 1
## 31-setosa 32-setosa 33-setosa 34-setosa 35-setosa
## 1 3 5 5 1
## 36-setosa 37-setosa 38-setosa 39-setosa 40-setosa
## 1 3 1 2 1
## 41-setosa 42-setosa 43-setosa 44-setosa 45-setosa
## 1 6 2 4 4
## 46-setosa 47-setosa 48-setosa 49-setosa 50-setosa
## 1 4 2 3 1
## 51-versicolor 52-versicolor 53-versicolor 54-versicolor 55-versicolor
## 7 8 7 9 7
## 56-versicolor 57-versicolor 58-versicolor 59-versicolor 60-versicolor
## 10 8 11 7 9
## 61-versicolor 62-versicolor 63-versicolor 64-versicolor 65-versicolor
## 11 10 12 8 9
## 66-versicolor 67-versicolor 68-versicolor 69-versicolor 70-versicolor
## 7 10 10 13 9
## 71-versicolor 72-versicolor 73-versicolor 74-versicolor 75-versicolor
## 14 10 15 8 8
## 76-versicolor 77-versicolor 78-versicolor 79-versicolor 80-versicolor
## 7 7 7 8 9
## 81-versicolor 82-versicolor 83-versicolor 84-versicolor 85-versicolor
## 9 9 10 15 10
## 86-versicolor 87-versicolor 88-versicolor 89-versicolor 90-versicolor
## 8 7 13 10 9
## 91-versicolor 92-versicolor 93-versicolor 94-versicolor 95-versicolor
## 10 8 10 11 10
## 96-versicolor 97-versicolor 98-versicolor 99-versicolor 100-versicolor
## 10 10 8 11 10
## 101-virginica 102-virginica 103-virginica 104-virginica 105-virginica
## 16 14 17 18 18
## 106-virginica 107-virginica 108-virginica 109-virginica 110-virginica
## 19 20 17 18 21
## 111-virginica 112-virginica 113-virginica 114-virginica 115-virginica
## 22 15 22 14 14
## 116-virginica 117-virginica 118-virginica 119-virginica 120-virginica
## 22 18 23 19 13
## 121-virginica 122-virginica 123-virginica 124-virginica 125-virginica
## 16 14 19 15 16
## 126-virginica 127-virginica 128-virginica 129-virginica 130-virginica
## 17 15 14 18 17
## 131-virginica 132-virginica 133-virginica 134-virginica 135-virginica
## 17 23 18 15 15
## 136-virginica 137-virginica 138-virginica 139-virginica 140-virginica
## 21 16 18 14 22
## 141-virginica 142-virginica 143-virginica 144-virginica 145-virginica
## 16 22 14 16 16
## 146-virginica 147-virginica 148-virginica 149-virginica 150-virginica
## 22 15 22 16 14
# For better visualizations, here is a ggplot2 wrapper, also visualizing single and average linkage
#install.packages("ggdendro")
library(ggdendro)
## Warning: package 'ggdendro' was built under R version 3.4.4
ggdendrogram(hclust(iris_dist, method = "complete"))
ggdendrogram(hclust(iris_dist, method = "average"))
ggdendrogram(hclust(iris_dist, method = "single"))
שיטה זו דורשת כוח חישוב חזק, משום שנדרש לחשב בה פונקציית מרחק בין נקודות רבות, לעומת KMeans (שם המרחק מחושב רק מ“מרכזי מסה”).
sample_n
דגמו 5,000 תצפיות מקובץ הנתונים של המטופלים (למה מדגם ולא כולם?)scale
.scale
השתמשו גם בפונקציה as.numeric
כדי להפוך את התוצאה לוקטורית ולא לרשימה.# If you decide to use Age, don't forget to scale it otherwise it might pull all the results in unwanted direction - it will have a lot of weight on the Euclidean distance function
# You can either scale using the scale function (it uses mean and standard deviation) or scale to 0-1 range.
appointments_sample <- appointments %>%
sample_n(5000) %>%
select(Age, Scholarship:SMS_received) %>%
mutate(age_scaled = as.numeric(scale(Age))) %>%
select(-Age)
# another option is to use a 0-1 scaling as follows
appointments_sample <- appointments %>%
sample_n(5000) %>%
select(Age, Scholarship:SMS_received) %>%
mutate(age_scaled = (Age - min(Age))/(max(Age)-min(Age))) %>%
select(-Age)
# Now continue to use dist() and hclust() as in the example above.