---
title: 'Übungszettel Clusteranalyse'
author: "Peter Zezula"
subtitle: "M.Psy.205, Dozent: Peter Zezula"
output:
  html_document:
    theme: paper
    toc: yes
    toc_depth: 2
    toc_float: yes
  pdf_document: default
header-includes:
 - \usepackage{comment}
params:
 soln: TRUE
mainfont: Helvetica
linkcolor: blue
---

## Links

[Übungszettel als PDF-Datei zum Drucken](https://md.psych.bio.uni-goettingen.de/mv/sheets/sheet_cluster.pdf)

`r if(!params$soln) {"\\begin{comment}"}`
**Übungszettel mit Lösungen**

[Lösungszettel als PDF-Datei zum Drucken](https://md.psych.bio.uni-goettingen.de/mv/sheets/sheet_cluster_solutions.pdf)

[Der gesamte Übugszettel als .Rmd-Datei](https://md.psych.bio.uni-goettingen.de/mv/sheets/sheet_cluster.Rmd) (Zum Downloaden: Rechtsklick > Speichern unter...)

`r if(!params$soln) {"\\end{comment}"}`

## Hinweise zur Bearbeitung

1. Bitte beantworten Sie die Fragen in einer .Rmd Datei. Sie können Sie über `Datei > Neue Datei > R Markdown...` eine neue R Markdown Datei erstellen. Den Text unter dem *Setup Chunk* (ab Zeile 11) können Sie löschen. [Unter diesem Link](https://md.psych.bio.uni-goettingen.de/mv/sheets/students_template.Rmd) können Sie auch unsere Vorlage-Datei herunterladen (Rechtsklick > Speichern unter...).
2. Informationen, die Sie für die Bearbeitung benötigen, finden Sie auf der [Website der Veranstaltung](https://www.psych.uni-goettingen.de/de/it/team/zezula/courses/multivariate)
3. Zögern Sie nicht, im Internet nach Lösungen zu suchen. Das effektive Suchen nach Lösungen für R-Probleme im Internet ist tatsächlich eine sehr nützliche Fähigkeit, auch Profis arbeiten auf diese Weise. Die beste Anlaufstelle dafür ist der [R-Bereich der Programmiererplattform Stackoverflow](https://stackoverflow.com/questions/tagged/r)
4. Auf der Website von R Studio finden Sie sehr [hilfreiche Übersichtszettel](https://www.rstudio.com/resources/cheatsheets/) zu vielen verschiedenen R-bezogenen Themen. Ein guter Anfang ist der [Base R Cheat Sheet](http://github.com/rstudio/cheatsheets/raw/master/base-r.pdf)

## Ressourcen

Die Clusteranalyse, um die es hier geht, wird in Field et al (2012) leider nicht dargestellt.
Es findet sich allerdings in Everitt (2010) ein Kapitel (Chapter 12).


## Tipp der Woche

R ist objektorientiert.
Alle R-Objekte haben Attributes, auf die wir zugreifen können.
Bei Dataframes und Tibbles haben wir häufig den `$` Operator benutzt.
Der funktioniert nicht nur beim Zugriff auf Spalten von Datentabellen, sondern universell.
Auch die  Ergebnisse von Funktionen, also Analysen, sind Objekte (Ergebnisobjekte).
Wir können Sie speichern und weiter benutzen. `res_obj <- lm(mpg ~ hp, data=mtcars)`
Eine Auflistung der Attribute erhalten wir über die Befehle `attributes()` oder detaillierter über `str()`.
Beide Befehle akzeptieren beliebige Objekte als Parameter.
Im Beispiel also `attributes(res_obj)` oder `str(res_obj)`.
Komfortablen Zugriff haben wir auch über den Aufklapp-Pfeil des Ergebnisobjekts im RStudio-Environment.
Die Summaries benutzen ein Ergebnisobjekt als Quelle und bereiten den Inhalt für eine Ausgabe auf.
Auch die Summaries können wir speichern und auf deren aufbereitete Attribute zugreifen, 
da auch Summaries Objekte mit Attribunten sind.
Wir können die Attribute direkt weiter benutzen, beispielsweise die Koeffizienten `res_obj$coefficients`.
Es gibt zahlreiche Zugriffsmöglichkeiten.
<!-- todo -->


**Beispiel**

```{r, eval = FALSE}
res_obj <- lm(mpg ~ hp, data=mtcars)
# get the coefficients of the adapted model
res_obj$coefficients
# slicing works
res_obj$coefficients[1]
summary(res_obj)
# summaries are objects too
s_res_obj <- summary(res_obj)
# and we can access their  attributes
s_res_obj$adj.r.squared
```



## 1) Daten einlesen, allgemeines zum Thema

Clusteranalysen fassen Beobachtungen zu Gruppen zusammen, wobei meist mehrere Variablen miteinander kombiniert werden, um die Beobachtungen Gruppen zuzuordnen.
Basis für die Zusammenfassung sind, je nach Verfahren, verschieden Ähnlichkeits- und Distanzmaße sowohl der einzelnen Beobachtungen, als auch der Gruppen, die auf Basis der benutzten Erklärvariablen gebildet werden.
Es handelt sich also in der Regel um explorative Verfahren.

Besonderes Interesse finden Clusteranalysen in der Marktforschung.
Daher stammt auch das Beispiel hier aus dem Bereich der Kundenforschung.

In diesem Sheet stellen wir die Befehle `stats::kmeans()` und mehrere Befehle aus der `library(mclust)` vor.
Damit die Befehle gefunden werden, müssen die entsprechenden Packages geladen sein, oder wir müssen den direkten Aufruf benutzen, z. b. `mclust::densityMclust(...)`.


Der Original-Datensatz stammt von 
[https://www.kaggle.com/dev0914sharma/customer-clustering](https://www.kaggle.com/dev0914sharma/customer-clustering)]

The dataset consists of information about the purchasing behavior of 2,000 individuals from a given area when entering a physical ‘FMCG’ store. 
All data has been collected through the loyalty cards they use at checkout. 
The data has been preprocessed and there are no missing values. 
In addition, the volume of the dataset has been restricted and anonymised to protect the privacy of the customers.

Variable	Data type	Range	Description							

-	ID	numerical	Integer	Shows a unique identificator of a customer.							
											
-	Sex	categorical	{0,1}	Biological sex (gender) of a customer. In this dataset there are only 2 different options.							
	- 0	male							
  - 1	female							
											
- Marital status	categorical	{0,1}	Marital status of a customer.							
	- 0	single							
	-	1	non-single (divorced / separated / married / widowed)							
											
-	Age	numerical	Integer	The age of the customer in years, calculated as current year minus the year of birth of the customer at the time of creation of the dataset							
	-	18	Min value (the lowest age observed in the dataset)							
	-	76	Max value (the highest age observed in the dataset)							
											
-	Education	categorical	{0,1,2,3}	Level of education of the customer							
	-	0	other / unknown							
	-	1	high school							
	-	2	university							
	-	3	graduate school
											
-	Income	numerical	Real	Self-reported annual income in US dollars of the customer.							
	-	35832	Min value (the lowest income observed in the dataset)							
	-	309364	Max value (the highest income observed in the dataset)							
											
-	Occupation	categorical	{0,1,2}	Category of occupation of the customer.							
	-	0	unemployed / unskilled							
	-	1	skilled employee / official							
	-	2	management / self-employed / highly qualified employee / officer							
											
-	Settlement size	categorical	{0,1,2}	The size of the city that the customer lives in.							
	-	0	small city							
	-	1	mid-sized city							
	-	2	big city							

Machen Sie sich mit dem Datensatz und seiner Struktur vertraut.

Wir stellen eine Kopie des Datensatzes auch über den Link [https://md.psych.bio.uni-goettingen.de/mv/data/div/segmentation_data.csv](https://md.psych.bio.uni-goettingen.de/mv/data/div/segmentation_data.csv) zur Verfügung.


### Aufg. 1.1 Datensatz laden
  Laden Sie den Datensatz `segmentation_data.csv` in R, auf den Sie über den Link [https://md.psych.bio.uni-goettingen.de/mv/data/div/segmentation_data.csv](https://md.psych.bio.uni-goettingen.de/mv/data/div/segmentation_data.csv) Zugriff haben. Nennen Sie das Datenobjekt `dd`.

`r if(!params$soln) {"\\begin{comment}"}`
#### Lösung

```{r}
library(tidyverse)
# we set the random seed to get equal results. 
# As with `kmeans()` the combination of Windows and MacOS and Knitting produce different results, we repeat it before kmeans() calls
set.seed(2341)  
# we read from a local server for conveniance
dd <- readr::read_csv("https://md.psych.bio.uni-goettingen.de/mv/data/div/segmentation_data.csv")
```
`r if(!params$soln) {"\\end{comment}"}`


### Aufg. 1.2 Umbenennen der Variablen
   Die originalen Spaltennamen sind nicht gut handhabbar. 
   Benennen Sie die Spalten also um. 
   Benutzen Sie hierzu beispielsweise den Befehl `colnames()`.
   Ein lauffähiger Befehl wäre z. B. `colnames(dd) <- c("id", "genderf", "marital_status", "age", "education", "income", "occupation", "sett_size")`

`r if(!params$soln) {"\\begin{comment}"}`
### Lösung

```{r}
colnames(dd) <- c("id", "genderf", "marital_status", "age", "education", "income", "occupation", "sett_size")
# we take a look at the data structure
head(dd)
```

`r if(!params$soln) {"\\end{comment}"}`

### Aufg. 1.3 Umskalieren der Variablen
   
Oft empfiehlt es sich, die Cluster-Variablen gleich zu skalieren, da sie sonst unterschiedlich stark in die Distanzmaße eingehen.
Das kann über Variablen gleicher Skalierung passieren oder über eine Umskalierung verschieden skalierter Variablen.
Die einfachste Variante ist dabei die z-Transformation, die in R sehr einfach über den Befehl `scale()` erreicht werden kann.

Erzeugen Sie z-transformierte Varianten der Variablen "genderf", "marital_status", "age", "education", "income", "occupation", "sett_size" und speichern Sie sie in neuen Variablen mit einem an den unstandardisierten Namen angehängtes "_z".

Tipp: `scale()` erzeugt eine Matrix als Ergebnis. 
Um die zurück in einen Data-Frame zu wandeln, können Sie z. B. den Befehl `data.frame()` benutzen.

Hängen Sie die z-standardisierten Variablen an das existierende Datenobjekt an.

`r if(!params$soln) {"\\begin{comment}"}`
### Lösung

```{r}
dd.t <- dd %>% dplyr::select(genderf:sett_size) %>% scale() %>% data.frame
colnames(dd.t) <- c("genderf_z", "marital_status_z", "age_z", "education_z", "income_z", "occupation_z", "sett_size_z")
dd <- cbind(dd, dd.t)
# we take a look at the data structure
head(dd)
```

`r if(!params$soln) {"\\end{comment}"}`





## 2) Dentrogramm erstellen, Clusterzugehörigkeit speichern

Ein gängiges Vorgehen bei der Clusterung von Beobachtungen ist das Erstellen eine Dentrogramms.
Dentrogramme stellen die Beobachtungen und deren sukkzessives Zusammenfassen zu Gruppen graphisch dar.
Für das Erstellen eines Dentrogramms muss festgelegt werden, welches Prinzip für das Zusammenfassen benutzt werden soll.
Gängig sind hier z. B. "Single Linkage", "Complete Linkage", "Average Linkage" etc.

Da wir in unserem Beispiel einen großen Datensatz mit 2000 Beobachtungen haben, würde das Dentrogramm sehr unübersichlich werden.
Uns geht es hier hauptsächlich um eine Demonstration des Prinzips. 
Daher lassen wir ein Dentrogramm von einer Zufallsauswahl der Beobachtungen erstellen.

### Aufg. 2.1 Sample erstellen

Erstellen Sie eine Zufallsauswahl von 50 Beobachtungen aus dem Datensatz und speichern Sie diese Auswahl in einem Datenobjekt mit Namen `dd.s`
Sie können hierzu beispielsweise den Befehl `sample` benutzen. 
`?sample()` hilft, wenn Sie nicht wissen, wie der Befehl funktioniert (oder natürlich eine Suche im WWW).
Sorgen Sie zusätzlich dafür, dass nur die z-standardisierten Spalten in dem Teildatensatz vorhanden sind.


`r if(!params$soln) {"\\begin{comment}"}`
### Lösung

```{r}
s.sel <- sample(dd$id, 50)
dd.s <- dd[dd$id %in% s.sel,] %>% dplyr::select(genderf_z:sett_size_z)
```

`r if(!params$soln) {"\\end{comment}"}`

### Aufg. 2.2 Distanzmatrix erstellen

Erstellen Sie eine Distanzmatrix der so ausgewählten Beobachtungen. 
Hierzu können Sie den Befehl `dist()` benutzen.
Werfen Sie einen Blick auf die Distanzmatrix.
`r if(!params$soln) {"\\begin{comment}"}`
### Lösung

```{r}
dists <- dd.s %>% dist()
# some distances ...
dists[1:10]
```

`r if(!params$soln) {"\\end{comment}"}`

### Aufg. 2.3 Dentrogramm erstellen

Erstellen Sie ein Dentrogramm für die 50 ausgewählten Beobachtungen. 
Wählen Sie dabei die Methode "Complete Linkage".
Sie können hierzu den Befehl `plot()` auf das Ergebnis des Befehls `hclust()` anwenden, der wiederum den Parameter `method=...` verarbeiten kann.
[https://www.rdocumentation.org/packages/stats/versions/3.6.2/topics/hclust](https://www.rdocumentation.org/packages/stats/versions/3.6.2/topics/hclust)
`r if(!params$soln) {"\\begin{comment}"}`
### Lösung

```{r}
plot(hclust(dists, method="complete"),ylab="Height", sub="Complete linkage")
```

`r if(!params$soln) {"\\end{comment}"}`

### Aufg. 2.4 Speichern von Clusterzugehörigkeiten

Speichern Sie für die ausgewählten Beobachtungen die Clusterzugehörigkeit, wenn Sie eine "Höhe" von 5 als Kriterium anwenden in einer neuen Spalte namens `ch_4`.

Speichern Sie außerdem die Clusterzugeörigkeit der ausgewählten Beobachtungen, wenn Sie genau 4 Cluster erhalten wollen. Geben Sie der Ergebnisspalte den Namen `cn_4`.

Für beides können Sie den Befehl `cutree` benutzen. 
Finden Sie heraus, wie das geht.

`r if(!params$soln) {"\\begin{comment}"}`
#### Lösung

```{r}
# we can get cluster membership for our observations for a specific method at a specific height
cutree(hclust(dists,method="complete"),h=5)
# and store it (h is Height) h=5 results in 4 clusters, therefore the name dd.s$ch_4
dd.s$ch_4 <- cutree(hclust(dists,method="complete"),h=5)
# psych::describe(dd.s$ch_4)
# we can also store membership for a certain number of clusters
dd.s$cn_4 <- cutree(hclust(dists,method="complete"),k=4)
# we look at the resulting cluster memberships
dd.s$ch_4
# ... and take a look at it
head(dd.s)
```

`r if(!params$soln) {"\\end{comment}"}`


## 3) Herausforderung: Elbow Plot und Anzahl von Clustern

Wie bei anderen explorativen Verfahren, z. B. (eFA)[sheet_pca_fa.html], ist nicht klar, in wie viele Cluster die Beobachtungen am besten aufgeteilt werden.
Hierzu hilft ein dem von der eFA bekannten Screeplot ähnliches Vorgehen.
Hierzu werden die within SS (Varianz der Distanzen in den Clustern) bzw. die between SS (Varianz der Abstände zwischen den Clustern) für eine aufsteigende Anzahl von Clustern geplottet.
Danach wird versucht, in dem Verlauf einen markanten Knick zu finden (Elbow).
Dies kann helfen, eine geeignete Anzahl von Clustern festzulegen.
Hier gibt es natürlich subjektiven Spielraum.

Bemerkung: Wenn Sie hier Schwierigkeiten haben, 
schauen Sie sich einfach das unten verlinkte Ergebnis an und machen Sie mit Aufgabe 4 weiter.


### Aufg. 3.1 Arbeiten mit einer Schleife und Attributen von Ergebnisobjekten

Notwendiger Hintergrund: Der Befehl `kmeans()` clustert Daten und erstellt eine bestimmte Menge von Clustern.
Die Menge der zu erstellenden Cluster wird bei `kmeans()` über den Parameter `centers` festgelegt.

Erstellen Sie eine Schleife, in der ein Index `k` von 1 - 10 laufen soll.
Schleifen in R funktionieren nach dem Prinzip:
`for (Sequenz){Befehle}`. Als `Sequenz` könnte z. B. stehen: `k in 1:10`.
Hierdurch ist im Schleifenkörper `k` mit seinem jeweils aktuellen Wert bekannt.
Rufen Sie im Schleifenkörper den Befehl `kmeans()` auf und übergeben Sie dem Befehl den Parameter `centers` mit der jeweiligen Ausprägung von `k`.
Als ersten Parameter erwartet `kmeans()` ein Datenobjekt.
Dieses Datenobjekt soll `dd` sein, allerdings nur die Spalten `dd$genderf` bis `dd$sett_size`.
Benutzen Sie wahlweise den Befehl `%>%` oder die positionale Übergabe.
Lassen Sie sich in der Loop den Parameter `tot.withinss` ausgeben.


`r if(!params$soln) {"\\begin{comment}"}`
#### Lösung

```{r}
set.seed(2341)
for (k in 1:10) {
  model <- dd %>% dplyr::select(genderf_z:sett_size_z) %>% kmeans(centers=k, iter.max=1000, nstart=1000)
  cat(model$tot.withinss)
  cat('; ')
}
```
`r if(!params$soln) {"\\end{comment}"}`


### Aufg. 3.2 Erstellen eines Ergebnis-Datenobjekts

Erstellen Sie einen Dataframe, in dem als Zeile die Kernergebnisse der oben ausgeführten `kmeans()` Analysen stehen. Dies sollen als Spalten sein:
- k            (Anzahl der Cluster)
- tot.withinss (gibt es als Property des Ergebnisobjekts von `kmeans()`)
- betweenss    (gibt es als Property des Ergebnisobjekts von `kmeans()`)
- totss        (gibt es als Property des Ergebnisobjekts von `kmeans()`)

`r if(!params$soln) {"\\begin{comment}"}`
#### Lösung

```{r}
set.seed(2341)
criteria <- data.frame()
nk <- 1:10
for (k in nk) {
  model <- dd %>% dplyr::select(genderf_z:sett_size_z) %>% kmeans(centers=k, iter.max=1000, nstart=1000)
  criteria <- rbind(criteria,c(k, model$tot.withinss, model$betweenss, model$totss))
}
# renaming columns
names(criteria) <- c("k","tot.withinss","betweenss","totalss")
```
`r if(!params$soln) {"\\end{comment}"}`

### Aufg. 3.3 Erstellen eines Elbow Plots

Erstellen Sie eine Grafik, in der auf der x-Achse die Anzahl der Cluster und auf der y-Achse die `tot.withinss` für die jeweilige Anzahl der Cluster grafisch dargestellt werden.

`r if(!params$soln) {"\\begin{comment}"}`
#### Lösung

```{r}
#scree plot
ggplot(criteria, aes(x=k)) +
  geom_point(aes(y=tot.withinss),color="red") +
  geom_line(aes(y=tot.withinss),color="red") +
  geom_point(aes(y=betweenss),color="blue") +
  geom_line(aes(y=betweenss),color="blue") +
  xlab("k = number of clusters") + ylab("Sum of Squares (within = red, between = blue)")
```
`r if(!params$soln) {"\\end{comment}"}`


### Aufg. 3.4 Grafikbasierte Entscheidung

Sollten Sie Schwierigkeiten bei der Umsetzung von Aufg. 3.1 - 3.3 haben, finden Sie die fertige Grafik 
[hier](https://md.psych.bio.uni-goettingen.de/mv/unit/cluster/elbow_plot.png).

Entscheiden Sie sich auf Basis der erstellten Grafik für eine Ihrer Ansicht nach adäquaten Anzahl von Clustern.

`r if(!params$soln) {"\\begin{comment}"}`
#### Lösung

Vermutlich kommen Sie auf 4 oder 5 Cluster.
`r if(!params$soln) {"\\end{comment}"}`




## 4) Cluster mit `kmeans()` bilden

Nehmen wir an, Sie hätten sich für 4 Cluster entschieden.

### Aufg. 4.1 Ansatz mit 4 Clustern

Erstellen Sie ein Modell mit 4 Clustern. 
Benutzen Sie hierbei alle Variablen des Datensatzes `dd`, bis auf die erste Spalte `dd$id` zur Bildung der Cluster.
Benutzen Sie hierfür den Befehl `kmeans()`
Speichern Sie das Modell als Ergebnisobjekt unter dem Namen `model`
Schauen Sie sich an, was Ihnen das Ergebnisobjekt so alles zu bieten hat.
Sie können hierfür den Befehl `attributes()` nutzen, der Ihnen die Namen aller Attribute ausgibt, die ein Objekt hat.

`r if(!params$soln) {"\\begin{comment}"}`
#### Lösung

```{r}
library(scales) # to manage colors via hue_pal()
# k-means 4 Clusters and use the scores
set.seed(2341) 
n_clusters = 4
model <- dd %>% dplyr::select(genderf_z:sett_size_z) %>% kmeans(centers=n_clusters, iter.max=1000, nstart=1000)
attributes(model)
```
`r if(!params$soln) {"\\end{comment}"}`


### Aufg. 4.2 Speichern der Clusterzuordnung

Speichern Sie die Clusterzugehörigkeit der Beobachtungen in einer Spalte mit Namen `dd$kmc_4`

Lassen Sie sich die Menge der Beobachtungen ausgeben, die den jeweiligen Clustern angehören.

`r if(!params$soln) {"\\begin{comment}"}`
#### Lösung

```{r}
# if we want to use the clusters furtheron f. e. for some analyses, we store the cluster assignment
dd$kmc_4 <- model$cluster
# or even better
dd$kmc_4 <- factor(model$cluster)
table(dd$kmc_4)
```
`r if(!params$soln) {"\\end{comment}"}`



### Aufg. 4.2 Inspektion der Clusterzentren

Die Clusterzentren sind die Mittelwerte der geclusterten Variablen für das jeweilige Cluster.
Lassen Sie sich die Clusterzentren ausgeben.

Inspizieren Sie die Clusterzentren - was fällt Ihnen auf?

`r if(!params$soln) {"\\begin{comment}"}`
#### Lösung

```{r}
model$centers
# these are the standardized means
# to get the original means of the clusters we can:
# dd %>% dplyr::group_by(kmc_4) %>% dplyr::select(genderf:sett_size) %>% dplyr::summarize_all(mean)
( m_u <- dd %>% dplyr::group_by(kmc_4) %>% dplyr::select(genderf:sett_size) %>% dplyr::summarize_all(mean) )
```

Wir könnten z. B. ein Cluster (meist Nr 2) als eine besondere Untergruppe identifizieren. 
Es handelt sich überwiegend um eher ältere, verheiratete etwa gleich viele Männer oder Frauen, die sehr gut gebildet sind und ein vergleichsweise hohes Einkommen in einer guten Position haben.

`r if(!params$soln) {"\\end{comment}"}`






### Aufg. 4.4 Visualisierung der Clusterzuordnung

Visualisieren Sie die gebildeten Cluster in einem Scatterplot, in dem das Alter gegen das Einkommen geplottet ist.

`r if(!params$soln) {"\\begin{comment}"}`
#### Lösung

```{r}
# we look at clusters in a scatterplot of age and income
dd %>% ggplot(aes(x=age_z,y=income_z, color=kmc_4)) +
  geom_point(alpha=.6) +#plotting alll the points
  #plotting the centroids
  geom_point(aes(x=model$centers[1,"age_z"],y=model$centers[1,"income_z"]),color=hue_pal()(n_clusters)[1],size=5,shape=18) +
  geom_point(aes(x=model$centers[2,"age_z"],y=model$centers[2,"income_z"]),color=hue_pal()(n_clusters)[2],size=5,shape=18) +
  geom_point(aes(x=model$centers[3,"age_z"],y=model$centers[3,"income_z"]),color=hue_pal()(n_clusters)[3],size=5,shape=18) +
  geom_point(aes(x=model$centers[4,"age_z"],y=model$centers[4,"income_z"]),color=hue_pal()(n_clusters)[4],size=5,shape=18) 
  # geom_point(aes(x=model$centers[5,"age_z"],y=model$centers[5,"income_z"]),color=hue_pal()(n_clusters)[5],size=5,shape=18) 

# we store the above calculated unstandardized means
m_u <- dd %>% dplyr::group_by(kmc_4) %>% dplyr::select(genderf:sett_size) %>% dplyr::summarize_all(mean)

# we look at clusters in a scatterplot of age and income
dd %>% ggplot(aes(x=age,y=income, color=kmc_4)) +
  geom_point(alpha=.6) +#plotting alll the points
  #plotting the centroids
  geom_point(aes(x=as.numeric(m_u[1,"age"]),y=as.numeric(m_u[1,"income"])),color=hue_pal()(n_clusters)[1],size=5,shape=18) +
  geom_point(aes(x=as.numeric(m_u[2,"age"]),y=as.numeric(m_u[2,"income"])),color=hue_pal()(n_clusters)[2],size=5,shape=18) +
  geom_point(aes(x=as.numeric(m_u[3,"age"]),y=as.numeric(m_u[3,"income"])),color=hue_pal()(n_clusters)[3],size=5,shape=18) +
  geom_point(aes(x=as.numeric(m_u[4,"age"]),y=as.numeric(m_u[4,"income"])),color=hue_pal()(n_clusters)[4],size=5,shape=18) 
  # geom_point(aes(x=as.numeric(m_u[5,"age"]),y=as.numeric(m_u[5,"income"])),color=hue_pal()(n_clusters)[5],size=5,shape=18) 

```
`r if(!params$soln) {"\\end{comment}"}`


## 5) Rendern

Lassen Sie die Datei mit `Strg` + `Shift` + `K` (Windows) oder `Cmd` + `Shift` + `K` (Mac) rendern. Sie sollten nun eine "schön aufpolierte" Version ihrer Datei sehen. Falls das klappt: Herzlichen Glückwunsch! Ihr Code kann vollständig ohne Fehlermeldung gerendert werden. Falls nicht: Nur mut, das wird schon noch! Gehen Sie auf Fehlersuche! Ansonsten schaffen wir es ja in der Übung vielleicht gemeinsam. 


## 6) Abschlussbemerkungen

Die Clusterung mit `kmeans()` ist stark abhängig von der Zufalls-Initialisierung der Cluster. 
Daher haben wir in den Beispielen oben einige Parameter hoch gesetzt. `iter.max=1000` und `nstart=1000`. 
Außerdem haben wir den Random Generator von R unmittelbar vor dem Aufruf von `kmeans()` initialisiert mit `set.seed(2341)`, um möglichst vergleichbare bzw. reproduzierbare Ergebnisse zu bekommen.
Wegen der starken Überlappungen unserer Cluster ist ein stabile Zuordnung der Beobachtungen zu Clustern ebenfalls erschwert.


## Literatur bzw. Quellen

*Anmerkung*: Dieser Übungszettel basiert auf Daten und Beispielen, die von der Website [https://www.kaggle.com/](https://www.kaggle.com/) stammen. 
Sie wurden für den Zweck dieser Übung modifiziert und entsprechender R-Code generiert.



Version: `r format(Sys.time(), '%d %B, %Y %H:%M')`