title |
author |
date |
output |
聚类分析 |
[zhangjian](https://gitee.com/jefeerzhang) |
`r Sys.Date()` |
html_document |
css |
includes |
toc |
toc_depth |
styles.css |
|
true |
2 |
|
|
```{r setup, include=FALSE}
knitr::opts_chunk$set(
echo = TRUE,
message = FALSE,
warning = FALSE
)
```
## 什么是聚类??一个简单的例子
![](https://gitee.com/jefeerzhang/forcast/raw/master/image/1.png)
### 探索性数据分析(EDA)的一种形式,将样本通过特征划分成具有共同特征的有意义的族群。
### 聚类分析的全部流程图
![流程](https://gitee.com/jefeerzhang/forcast/raw/master/image/2.png)
## 定义距离和相似性
$$距离 = 1-相似性$$
![距离的直观定义](https://gitee.com/jefeerzhang/forcast/raw/master/image/3.png)
$$距离=\sqrt{\left(\mathbf{X}_{\text {red }}-\mathbf{X}_{\text {blue }}\right)^{2}+\left(\mathbf{Y}_{\text {red }}-\mathbf{Y}_{\text {blue }}\right)^{2}}$$
```{r}
library(tidyverse)
library(ggthemes)
library(ggfortify)
library(DT)
two_person % datatable()
```
$$\text { height }_{\text {scaled}}=\frac{\text {height - mean(height)}}{\text {sd}(\text {height})}$$
```{r}
dist(three_person)
scale(three_person)
dist(scale(three_person))
```
上面一个简单的例子,我们可以看出数据的尺度对我们计算距离有很大影响。
## 如何计算类别变量(categorical)的距离
我们还是看一个例子
```{r}
kouwei % datatable()
```
### 如何计算上述口味例子的距离呢?
- 首先我们定义 $J(A, B)=\frac{A \cap B}{A \cup B}$来计算类别型变量的相似度
- 假设我们希望计算样本1和样本2的距离,根据上面的定义,我们有
$$J(1,2)=\frac{1 \cap 2}{1 \cup 2}=\frac{1}{4}$$
那么1和2的距离为$1-J(1,2)=1-\frac{1}{4}=0.75$
如果使用软件计算
```{r}
dist(kouwei,method = 'binary')
```
### 如果类别变量多于两个,如何计算距离与相似度?如果你的数据如下,如何处理?
```{r}
teacher_sat % datatable()
```
### 面对上述类型的数据,我们需要将多种类型数据处理成虚拟变量,才能进行距离和相似度的计算
```{r}
library(dummies)
teacher_sat_df %
mutate(group = cluster_assignments)
ggplot(data = play_6_k2 ,aes(x=x,y=y,color=as.factor(group)))+geom_point(size=3)+theme_clean()+
ggtitle('分两组情况')
cluster_assignments %
mutate(group = cluster_assignments)
ggplot(data = play_6_k2 ,aes(x=x,y=y,color=as.factor(group)))+geom_point(size=3)+theme_clean()+
ggtitle('分三组情况')
```
## Kmeans的思想:
> 一个好的聚类算法,应该是能够使得类内的差异尽可能小。设$W(C_k)$是第$C_k$类中差异化的度量,因此我们的问题转化为:
$$\min \left\\{ {\sum\limits_{k = 1}^K {W({C_k})} } \right\\}$$
### 使用平方欧式距离定界定类内差异
$$W({C_k}) = \frac{1}{{\left| {{C_k}} \right|}}{\sum\limits_{i,i' \in {C_k}} {\sum\limits_{j = 1}^p {({x_{ij}} - {x_{i'j}})} } ^2}$$
$$\min \left\\{ {\sum\limits_{k = 1}^K {\frac{1}{{\left| {{C_k}} \right|}}{{\sum\limits_{i,i' \in {C_k}} {\sum\limits_{j = 1}^p {({x_{ij}} - {x_{i'j}})} } }^2}} } \right\\}$$
### 具体算法:
> 1 随机为每个观测值分配一个1到K的数字
> 2 遍历所有数据,将每个数据划分到最近的中心点中
> 3 计算每个聚类的平均值,并作为新的中心点
> 4 重复2-3,直到这k个中线点不再变化(收敛了),或执行了足够多的迭代
![](https://upload-images.jianshu.io/upload_images/8116044-80981f3cb8255a01.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
### 上图展示了K=3的Kmeans聚类算法过程,先给每个观测值随机分配1-3的数字,然后算出这些1-3类的中心,第一行第三个图展示了这个中心;左下第一张图,每个观测值被分配到了与之最接近的类中;第二行第二列图,重新计算不同类的中心;第二行第三列反复迭代后的结果。我们先虚拟一个项目
```{r}
set.seed(123)
x %
select(city,aqi ,pm25,pm10,no2,o3,co,so2) %>%
drop_na()
aqi_sum %
group_by(city) %>%
summarise(pm25_m =mean(pm25),so2_m = mean(so2),pm10_m=mean(pm10),no2_m=mean(no2),co_m=mean(co))
rownames(aqi_sum)