一. 相关背景与方法
1. 数据来源
数据来自《Python数据分析与挖掘实战》书第14章, 该章意在使用运营商通过手机基站搜集的用户历史定位数据,采用数据挖掘技术对基站进行分群并对不同的商圈分群进行特征分析,以选取合适的商圈进行促销.
2. 层次聚类
层次聚类试图在不同层次对数据集进行划分, 从而形成树形的聚类结构. 数据集的划分可采用“自底向上”的聚合策略, 也可采用“自顶向下”的分拆策略.
其中, 自底向上的策略先将数据集中的每个样本看作一个初始聚类簇, 然后在算法运行的每一步中找出距离最近的两个聚类簇进行合并, 该过程不断重复, 直至达到预设的聚类簇个数; 自顶向下的策略, 先将所有对象置于同一个簇中, 然后逐渐细分为越来越小的簇, 直到每个对象自成一簇, 或者达到了某个终止条件. 常用的为自底向上策略.
(转自 https://blog.csdn.net/sinat_33519513/article/details/79078486 )
3. 离差标准化
又做0~1标准化, 它是对原始数据进行线性变换, 使结果落到 [0,1] 区间.
公式:
二. 数据分析
1. 读取数据与规范化
原始数据为处理过后的基站数据, 包含基站编号与其对应的工作日上班时间人均停留时间, 凌晨人均停留时间, 周末人均停留时间, 周末人均停留时间, 日人均流量, 数据各列均无缺失值.
由于各属性之间的差异较大, 为消除数量级数据带来的影响, 在进行聚类前, 对数据进行了离差标准化处理, 并把处理后的数据进行了保存.
相关代码:
# -*- coding:utf-8 -*-
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
inputfile = './data/business_circle.xls'
outputfile = './data/standardized.xls'
# 加载数据
data = pd.read_excel(inputfile, index_col='基站编号')
# print(data.head(5))
# print(data.info())
# 离差标准化
mm = MinMaxScaler()
data = pd.DataFrame(mm.fit_transform(data.values), index=data.index, columns=data.columns)
data = data.reset_index()
print(data.head(10))
data.to_excel(outputfile, index=False)
2. 谱系聚类图
使用python画出数据的谱系聚类图如下, 从图中确定聚类类别数 k = 3 较为合适.
相关代码:
# -*- coding:utf-8 -*-
import pandas as pd
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import linkage, dendrogram
filepath = './data/standardized.xls'
data = pd.read_excel(filepath, index_col='基站编号')
# scipy 层次聚类函数
Z = linkage(data, method='ward', metric='euclidean') # 谱系聚类图
P = dendrogram(Z, 0) # 画谱系聚类图
plt.show()
3. 聚类分析
python中sklearn工具包提供 AgglomerativeClustering() 函数进行层次聚类. 读取标准化后的数据并建立模型, 传入参数 n_clusters = 3 指定需要分类的类别数为3.
在聚类后把聚类类别标签与相应的基站数据合并, 对每一聚类的数据进行绘图表示, 图片如下:
从上图可知, 商圈类别1日均人流量大, 工作日、凌晨及周末人均停留时间较短, 该类别所覆盖的区域应该为商业区; 商圈类别2凌晨和周末人均停留时间明显较长, 可判定为住宅区; 而根据商圈类别3图中所反映现象可知其基站覆盖的区域为上班区域.
相关代码:
# -*- coding:utf-8 -*-
import pandas as pd
from sklearn.cluster import AgglomerativeClustering # sklearn中的层次聚类函数
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
filepath = './data/standardized.xls'
k = 3 # 聚类数
data = pd.read_excel(filepath, index_col='基站编号')
model = AgglomerativeClustering(n_clusters=k, linkage='ward')
model.fit(data)
# 详细输出原始数据及其类别
r = pd.concat([data, pd.Series(model.labels_, index=data.index, name='聚类类别')], axis=1)
print(r.head(10))
# 画图
style = ['ro-', 'bo-', 'go-']
for i in range(k):
plt.figure()
tmp = r[r['聚类类别'] == i].iloc[:, :4]
for j in range(len(tmp)):
plt.plot(range(1, 5), tmp.iloc[j], style[i])
plt.title('商圈类别' + str(i+1), fontsize=20)
plt.xticks(range(1, 5), data.columns, rotation=20)
plt.subplots_adjust(bottom = .18) # 调整底部, 让标签显示完全
plt.show()
详细数据及代码请点击: GitHub