20210202业务总结:K-means和分层聚类

由于论文需求,在前人基础上做了K-means和分层聚类,并且搭建了一下pandas处理数据的工作流。这篇文章记录一下两段聚类的代码,很多细节理解得还不够深入,我会后面碰到了再钻研并补充。

K-means:对13个特征,105个对象做分类。输出结果到新增的列,没有可视化。保持csv文件的标题栏是英文,这样比较不容易出现编码错误。

from copy import deepcopy
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
plt.rcParams['figure.figsize'] = (16, 9)
plt.style.use('ggplot')

# 数据标准化
def Normalization(x):
    return [(float(i) - min(x)) / float(max(x) - min(x)) for i in x]

# 按行的方式计算两个坐标点之间的距离
def dist(a, b, ax=1):
    return np.linalg.norm(a - b, axis=ax)


# 导入数据集
data = pd.read_csv('E:/学位论文相关/县乡分类研究/henan_self_organization.csv')
data = data.dropna(axis=0,how='all')  # 去除空行
data = data.dropna(axis=1,how='all')  # 去除空列
data = data.fillna(0)
print(data.tail(5))

# 将csv文件中的数据转换为二维数组
f1 = data['城镇化率'].values
f2 = data['建成区路网密度'].values
f3 = data['中心城市影响力等级'].values
f4 = data['户籍减常住'].values
f5 = data['人均GDP'].values
f6 = data['非农产值变化'].values
f7 = data['城镇人口变化'].values
f8 = data['征用地面积'].values
f9 = data['固定资产投资增速'].values
f10 = data['高中毛入学率'].values
f11 = data['首位度'].values
f12 = data['单位用地GDP'].values
f13 = data['城乡收入比'].values

X = np.array(list(zip(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13)))
X = (X-X.min(axis=0))/(X.max(axis=0)-X.min(axis=0))
print(X.shape)




# 设定分区数
k = 3
# 随机获得中心点的坐标
n_sample, n_feature = X.shape  # 获取数据:传进105个数据,13个特征
# 为了在数据范围内产生随机质心,首先计算各特征的统计量
f_mean = np.mean(X,axis=0)
f_std = np.std(X, axis=0)  # 求所有数据的均值和标准差
C= f_mean + np.random.randn(k, n_feature) * f_std  # 均值+随机值*标准差

# 用于保存中心点更新前的坐标
C_old = np.zeros(C.shape)
print(C)
# 用于保存数据所属中心点
clusters = np.zeros(len(X))
# 迭代标识位,通过计算新旧中心点的距离
iteration_flag = dist(C, C_old, 1)

tmp = 1
# 若中心点不再变化或循环次数不超过20次(此限制可取消),则退出循环
while iteration_flag.any() != 0 and tmp < 20:
    # 循环计算出每个点对应的最近中心点
    for i in range(len(X)):
        # 计算出每个点与中心点的距离
        distances = dist(X[i], C, 1)
        # print(distances)
        # 记录0 - k-1个点中距离近的点
        cluster = np.argmin(distances)
        # 记录每个样例点与哪个中心点距离最近
        clusters[i] = cluster

    # 采用深拷贝将当前的中心点保存下来
    C_old = deepcopy(C)
    # 从属于中心点放到一个数组中,然后按照列的方向取平均值
    for i in range(k):
        points = [X[j] for j in range(len(X)) if clusters[j] == i]
        C[i] = np.mean(points, axis=0)


    # 计算新旧节点的距离
    print('循环第%d次' % tmp)
    tmp = tmp + 1
    iteration_flag = dist(C, C_old, 1)
    print("新中心点与旧点的距离:", iteration_flag)
data['聚类结果'] = clusters
data.to_csv('E:/学位论文相关/县乡分类研究/henan_clf_2.csv', encoding = 'utf-8-sig')

分层聚类:树状图很炫,可以直接导入库来做可视化:(X是对上一段代码的沿用)

 Z = linkage(X, method='ward')
    dendrogram(Z,labels = name)
    # plt.show()
    plt.savefig("E:/学位论文相关/县乡分类研究/" + "cluster"+ ".png", dpi=700, bbox_inches="tight")

结果长这样:

具体的分层聚类代码来自于这一段,可以调整门槛值获得不同的聚类簇数。(改用别人的代码,后面有机会会继续补充)

import numpy as np
from scipy.cluster.hierarchy import dendrogram, linkage, fcluster
import pandas as pd
from scipy.cluster.hierarchy import linkage, dendrogram
from matplotlib import pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体)
plt.rcParams['figure.figsize'] = (10.0, 4.0)

def hierarchy_cluster(data, method='average', threshold=0.9):
    '''层次聚类

    Arguments:
        data [[0, float, ...], [float, 0, ...]] -- 文档 i 和文档 j 的距离

    Keyword Arguments:
        method {str} -- [linkage的方式: single、complete、average、centroid、median、ward] (default: {'average'})
        threshold {float} -- 聚类簇之间的距离
    Return:
        cluster_number int -- 聚类个数
        cluster [[idx1, idx2,..], [idx3]] -- 每一类下的索引
    '''
    data = np.array(data)

    Z = linkage(data, method=method)
    cluster_assignments = fcluster(Z, threshold, criterion='distance')
    print(type(cluster_assignments))
    num_clusters = cluster_assignments.max()
    indices = get_cluster_indices(cluster_assignments)

    return num_clusters, indices

def get_cluster_indices(cluster_assignments):
    '''映射每一类至原数据索引

    Arguments:
        cluster_assignments 层次聚类后的结果

    Returns:
        [[idx1, idx2,..], [idx3]] -- 每一类下的索引
    '''
    n = cluster_assignments.max()
    indices = []
    for cluster_number in range(1, n + 1):
        indices.append(np.where(cluster_assignments == cluster_number)[0])

    return indices

if __name__ == '__main__':
    # 导入数据集
    data = pd.read_csv('E:/学位论文相关/县乡分类研究/henan_self_organization.csv')
    data = data.dropna(axis=0, how='all')  # 去除空行
    data = data.dropna(axis=1, how='all')  # 去除空列
    data = data.fillna(0)
    print(data.tail(5))

    # 将csv文件中的数据转换为二维数组
    name = data['名称'].values
    f1 = data['城镇化率'].values
    f2 = data['建成区路网密度'].values
    f3 = data['中心城市影响力等级'].values
    f4 = data['户籍减常住'].values
    f5 = data['人均GDP'].values
    f6 = data['非农产值变化'].values
    f7 = data['城镇人口变化'].values
    f8 = data['征用地面积'].values
    f9 = data['固定资产投资增速'].values
    f10 = data['高中毛入学率'].values
    f11 = data['首位度'].values
    f12 = data['单位用地GDP'].values
    f13 = data['城乡收入比'].values

    X = np.array(list(zip(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13)))
    X = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
    print(X.shape)


    r, c = X.shape
    for i in range(r):
        for j in range(i, c):
            if X[i][j] != X[j][i]:
                X[i][j] = X[j][i]
    for i in range(r):
        for j in range(i, c):
            if X[i][j] != X[j][i]:
                print(X[i][j], X[j][i])

    num_clusters, indices = hierarchy_cluster(X)

    print("%d clusters" % num_clusters)
    for k, ind in enumerate(indices):
        print("cluster", k + 1, "is", ind)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值