客户分类:
1、将客户分为三类:超级VIP、vip、普通用户
2、需要你将不同的类的数据,在图上显示出来,用不同的颜色
3、返回三个类中,各包含哪些点
数据在下面的的表中,因为无法上传表格所以截了个图!
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import random
def decimal_clean(arr):
'''
将输入序列进行小数定标标准化
:param arr:输入的待优化的序列
:return:标准化后的序列
'''
k = np.ceil(np.log10(np.max(np.abs(arr))))
return arr / 10 ** k
def iter_self(xy_line, n_type):
'''
自我迭代函数, 自我生成n_type个随机参考点进行循环迭代, 每次迭代的最后利用本次分区结果求新的参考点
迭代退出条件, 新的参考点跟上一次的参考点位置一致
:param xy_line: 输入的x_y序列
:param n_type: 分类数目
:return: 划分完成的区域
'''
# 进入函数, 初始化旧参考点位置序列与新参考点位置序列
old_pos = [[random.random(), random.random()] for i in range(n_type)]
new_pos = [[] for i in range(n_type)]
# 进入循环迭代
while True:
# 每一次的循环都刷新一次分区列表
area = [[] for i in range(n_type)]
# 对每一个点遍历
for pos in range(len(xy_line)):
# 获得这个点的坐标
this_pos = [xy_line.iloc[pos, 0], xy_line.iloc[pos, 1]]
# 创建空列表,用于存放该点与各个参考点的欧式距离
distance = []
# 针对每一个点的坐标对所有中心点求欧式距离
for i in range(n_type):
distance.append(Oup_distance(this_pos, old_pos[i]))
# 找到所有距离中最小点的索引, 即该点属于第几区
min_index = distance.index(min(distance))
# 根据该点的区号, 进行分区
area[min_index].append(this_pos)
# 判断是否有空区域, 如果有, 重新调用本函数, 得到返回结果之后直接break
if [] in area:
area = iter_self(xy_line, n_type)
break
# 来到此步, 证明各个分区都是有值的, 用均值法求出各区对应的新的参考点坐标
new_pos = reflush_pos(area, n_type, new_pos)
# 判断新参考点与就参考点是否一致, 一致即可退出循环
if new_pos == old_pos:
break
else: # 否则将新的点序列深拷贝给旧的点序列, 新的点序列置空
old_pos = new_pos.copy()
new_pos = [[] for i in range(n_type)]
return area
def reflush_pos(area, n_type, pos):
'''
刷新参考点位置
:param area: 分区序列
:param n_type: 种类数目
:param pos: 用于存放新参考点的序列
:return: 新的参考点序列
'''
# 对area进行遍历
for i in range(n_type):
# 将area[i]深拷贝赋值给this, 在进行numpy数组转换
this = area[i].copy()
# 如果不进行深拷贝, 此步会将整个area转换成numpy数组
this_area = np.array(this)
# 求x序列和y序列的均值, 并赋值给pos
x_mean = np.mean(this_area[:, 0])
y_mean = np.mean(this_area[:, 1])
pos[i] = [x_mean, y_mean].copy()
return pos
def Oup_distance(pos1, pos2):
'''
计算两点之间的欧式距离
:param pos1:点1的(x, y)坐标
:param pos2:点2的(x, y)坐标
:return:两点之间的欧式距离值
'''
Oup = np.sqrt((pos1[1] - pos2[1]) ** 2 + (pos1[0] - pos2[0]) ** 2)
return Oup
company = pd.read_csv(r"C:\Users\Administrator\Desktop\company.csv", encoding="gbk")
# 这里用的是iloc的提取方法, 也可以根据个人习惯使用其他提取方法
# 此处特意将时间和消费金额两列作为x和y使用concat函数合并到一个dataframe, 方便后面的处理
x_y = pd.concat([decimal_clean(company.iloc[:, 2]), decimal_clean(company.iloc[:, 1])], axis=1, join="outer")
# 得到三维的列表AREA
AREA = iter_self(x_y, 3)
# 画图
plt.figure()
for area in AREA:
# area是二维列表,将其变为二维数组
area_np = np.array(area)
x = area_np[:, 0]
y = area_np[:, 1]
# 将x,y联系起来
plt.scatter(x, y)
# 显示画图
plt.show()