K-Means算法实现订单数据order.csv的聚类

1、介绍

1、概述
  其基本介绍如下:

2、代码功能
  通过本代码采用数据集后8个特征,初始时设置3个聚类中心,然后进行50次迭代之后,实现订单数据中的聚类。

2、代码

1、数据准备order.csv
(1)数据格式

"customer","order","total_items","discount%","weekday","hour","Food%","Fresh%","Drinks%","Home%","Beauty%","Health%","Baby%","Pets%"
0, 0, 45, 23.03, 4, 13, 9.46, 87.06, 3.48, 0, 0, 0, 0, 0
0, 1, 38, 1.22, 5, 13, 15.87, 75.8, 6.22, 2.12, 0, 0, 0, 0
0, 2, 51, 18.08, 4, 13, 16.88, 56.75, 3.37, 16.48, 6.53, 0, 0, 0
...

  为了大家能够更好的学习K-Means聚类算法,我将这个csv文件放到我博客的资源中,通过下面的链接即可下载,注意在将下面的文件放到代码中运行时,注意修改代码中的文件路径。

https://download.csdn.net/download/weixin_43334389/13183776

2、代码

# @Time : 2020/11/22 21:33
# @Author : Li Kunlun
# @Description : KMean算法,聚类算法
import numpy as np
import pandas as pd
# tqdm 是一个快速,可扩展的Python进度条,可以显示进度信息
from tqdm import tqdm

data = pd.read_csv(r"dataset/order.csv", header=0)
# 后8列都要
t = data.iloc[:, -8:]
print(t)


class KMeans:
    """
    @desc:Kmeans聚类算法实现
    """

    def __init__(self, k, times):
        """
        @desc:初始化
        @param k:聚成k个类
        @param times:迭代次数
        """
        self.k = k
        self.times = times

    def fit(self, X):
        """
        @desc:根据训练数据测试模型
        @param X:训练数据特征矩阵,数组类型[样本数量,特征数量]
        """
        X = np.asarray(X)
        # X.shape (30000, 8)
        print("X.shape", X.shape)
        # 设置随机数种子,以便于可以相同的随机系列,以便随机结果重现
        np.random.seed(0)
        # 从数组中随机选择K个点作为初始聚类中心
        self.cluster_centers_ = X[np.random.randint(0, len(X), self.k)]
        # 用于存放数据所属标签
        self.labels_ = np.zeros(len(X))
        # 开始迭代
        for t in tqdm(range(self.times)):
            # 循环遍历样本计算每个样本与聚类中心的距离
            for index, x in enumerate(X):
                # 计算每个样本与每个聚类中心的欧式距离,每行元素进行求和
                dis = np.sqrt(np.sum((x - self.cluster_centers_) ** 2, axis=1))
                # 将最小距离的索引赋值给标签数组,索引的值就是当前所属的簇。范围(0,K-1)
                self.labels_[index] = dis.argmin()
            # 循环遍历每一个数据然后更新聚类中心
            for i in range(self.k):
                # 计算每个簇内所有点的均值,用来更新聚类中心
                self.cluster_centers_[i] = np.mean(X[self.labels_ == i], axis=0)

    def predict(self, X):
        """
        @desc:预测样本属于那个簇
        @param X:训练数据特征矩阵,数组类型[样本数量,特征数量]
        @return:返回类数组,每一个x所属的簇
        """
        X = np.asarray(X)
        result = np.zeros(len(X))
        for index, x in enumerate(X):
            # 计算样本与聚类中心的距离
            dis = np.sqrt(np.sum((x - self.cluster_centers_) ** 2, axis=1))
            # 找到距离最近的聚类中中心划分一个类别
            result[index] = dis.argmin()
        return result


kmeans = KMeans(3, 50)
kmeans.fit(t)
print("kmeans.cluster_centers_", kmeans.cluster_centers_)

# 查看某个簇内的所有样本数据
# t[kmeans.labels_ == 0]

# 测试1:每个数据有8个特征 [0. 2. 1.]
print(kmeans.predict([[30, 30, 40, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 30, 30, 40], [30, 30, 0, 0, 0, 0, 20, 20]]))
# 测试2
# 需要注意loc函数是用字符作为索引的。并且包含:后面的那一列
# 按照标签进行选择。
t2 = data.loc[:, "Food%":"Fresh%"]
#    Food%  Fresh%
# 0   9.46   87.06
# 1  15.87   75.80
# 2  16.88   56.75
print(t2.head(3))
kmeans = KMeans(3, 50)
kmeans.fit(t2)

import matplotlib as mpl
import matplotlib.pyplot as plt

mpl.rcParams["font.family"] = "SimHei"
mpl.rcParams["axes.unicode_minus"] = False

# 设置画布,将其设置大一点,便于查看
plt.figure(figsize=(10, 10))
# 绘制每个类别散点图
plt.scatter(t2[kmeans.labels_ == 0].iloc[:, 0], t2[kmeans.labels_ == 0].iloc[:, 1], label="类别1")
plt.scatter(t2[kmeans.labels_ == 1].iloc[:, 0], t2[kmeans.labels_ == 1].iloc[:, 1], label="类别2")
plt.scatter(t2[kmeans.labels_ == 2].iloc[:, 0], t2[kmeans.labels_ == 2].iloc[:, 1], label="类别3")
# 绘制聚类中心,s=300设置的 + 号的大小
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], marker="+", s=300)
plt.title("食物与肉类购买聚类分析")
plt.xlabel("食物")
plt.ylabel("肉类")
plt.legend()
plt.show()

3、结果展示
(1)食物与肉类购买聚类分析


(2)聚类中心坐标

[[46.33977936  8.93380516 23.19047005 13.11741633  4.8107557   1.17283735
   1.35704647  0.95392773]
 [19.5308009  50.42856608 14.70652695  7.89437019  3.69829234  0.91000428
   1.92515077  0.82113238]
 [ 7.93541008  4.56182052 30.65583437 18.57726789  8.61597195  1.28482514
  26.81950293  1.30158264]]

3、分析

1、np.random.randint生成随机数组

# 默认high是None,如果只有low,那范围就是[0,low)。如果有high,范围就是[low,high)。
np.random.seed(0)
# [5 0]
print(np.random.randint(0, 10, 2))

# 生成2*4维度的二维数组
# [[3 3 3 1]
#  [3 2 4 0]]
print(np.random.randint(5, size=(2, 4)))

2、enumerate 类型举例

# enumerate 函数用于遍历序列中的元素以及它们的下标:
# 0 a
# 1 b
# 2 c
for index, value in enumerate(["a", "b", "c"]):
    print(index, value)

3、矩阵求和axis=0/1分析

a = np.array([[0, 2, 1], [3, 5, 6], [0, 1, 1]])  # 得到一个矩阵a
# [[0 2 1]
#  [3 5 6]
#  [0 1 1]]
print(a)
# 将a中所有元素求和 0+2+1+3+5+6+0+1+1=19
print(a.sum())
# 求出每行元素的和 [ 3 14  2]
print(np.sum(a, axis=1))
# 出每列元素的和 [3 8 8]
print(np.sum(a, axis=0))

4、loc/iloc区别

dates = pd.date_range("20130101", periods=3)
df = pd.DataFrame(np.arange(12).reshape(3, 4), index=dates, columns=['A', 'B', 'C', 'D'])
#             A  B   C   D
# 2013-01-01  0  1   2   3
# 2013-01-02  4  5   6   7
# 2013-01-03  8  9  10  11
print(df)
# 1。其中loc 用行列标签,iloc用数字索引。
print(df.loc['20130101', 'B'])
# 10
print(df.iloc[2, 2])
  • 9
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值