部分数据
Id | R | F | M |
1 | 27 | 6 | 232.61 |
2 | 3 | 5 | 1507.11 |
3 | 4 | 16 | 817.62 |
4 | 3 | 11 | 232.81 |
5 | 14 | 7 | 1913.05 |
6 | 19 | 6 | 220.07 |
7 | 5 | 2 | 615.83 |
8 | 26 | 2 | 1059.66 |
9 | 21 | 9 | 304.82 |
10 | 2 | 21 | 1227.96 |
11 | 15 | 2 | 521.02 |
12 | 26 | 3 | 438.22 |
13 | 17 | 11 | 1744.55 |
14 | 30 | 16 | 1957.44 |
15 | 5 | 7 | 1713.79 |
16 | 4 | 21 | 1768.11 |
17 | 93 | 2 | 1016.34 |
18 | 16 | 3 | 950.36 |
19 | 4 | 1 | 754.93 |
20 | 27 | 1 | 294.23 |
聚类算法实现
一、实验题目
数据库应用
二、实验内容
现在有部分餐饮客户的消费数据存于数据文件consumption.xls,其中R表示最近一次消费时间间隔,F表示消费频率,M表示消费总金额。编程实现K-Means聚类算法,将客户分类成3类客户群,并评价这些客户群的价值
三、实验目的
1、熟悉K-Means聚类算法
2、锻炼分析问题、解决问题并动手实践的能力
四、实验指导
1、自行采用一种语言编程实现算法(注意:生成聚类中心、分配对象类别、迭代调整等核心算法需自己编程实现)
2、用课堂例子进行正确性检验
3、用户界面友好,要考虑到输入输出
4、重复运行,分析结果,说明初始化对结果的影响
代码:
package home;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class k_means {
int k = 3; //聚类的类别
static int iteration = 0 ; // 聚类循环次数
static String a[] = {“20”, “8”, “400”}; //随机设置3个数据中心点
static String b[] = {“30”, “13”, “626.37”};
static String c[] = {“50”, “20”, “1105.63”};
static String[][] arr1 = new String[942][4]; //在getContrast()引用
static String[][] arr2 = new String[942][4];
static String[][] arr3 = new String[942][4];
public static void main(String[] args){
String[][] arr = new String[942][4]; //
init(arr);
getContrast(arr);
getPrint();
}
public static void init(String arr[][]){
int count = 0;
String[] array = null;
File file = new File(“consumption.csv”); //获取文件consumption.csv
try {
@SuppressWarnings(“resource”)
BufferedReader buf = new BufferedReader(new FileReader(file)); //读取文件
String s = null;
while((s=buf.readLine()) != null){
array = s.split(“,”);
arr[count][0] = array[0]; //将读取的数据中数据分别存到二维数组中
arr[count][1] = array[1];
arr[count][2] = array[2];
arr[count][3] = array[3];
count++;
}
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
public static void getContrast(String arr[][]){
float value1; //采用欧氏距离判断各个数据归属哪个类
float value2;
float value3;
while(iteration<500){ //循环执行500次,500次的作用数字大,才能聚类彻底,直到中心点不会在变
int count1 = 0;
int count2 = 0;
int count3 = 0;
float sum1_r = 0;
float sum1_f = 0;
float sum1_m = 0;
float sum2_r = 0;
float sum2_f = 0;
float sum2_m = 0;
float sum3_r = 0;
float sum3_f = 0;
float sum3_m = 0;
for(int i=1; i<941; i++){
//欧式算法公式 a=sqrt(pow(b,2)+pow(c,2)+pow(d,2))
value1 = (float) Math.sqrt(Math.pow(Float.parseFloat(arr[i][1])-Float.parseFloat(a[0]), 2)+
Math.pow(Float.parseFloat(arr[i][2])-Float.parseFloat(a[1]), 2) +
Math.pow(Float.parseFloat(arr[i][3])-Float.parseFloat(a[2]), 2));
value2 = (float) Math.sqrt(Math.pow(Float.parseFloat(arr[i][1])-Float.parseFloat(b[0]), 2)+
Math.pow(Float.parseFloat(arr[i][2])-Float.parseFloat(b[1]), 2) +
Math.pow(Float.parseFloat(arr[i][3])-Float.parseFloat(b[2]), 2));
value3 = (float) Math.sqrt(Math.pow(Float.parseFloat(arr[i][1])-Float.parseFloat(c[0]), 2)+
Math.pow(Float.parseFloat(arr[i][2])-Float.parseFloat(c[1]), 2) +
Math.pow(Float.parseFloat(arr[i][3])-Float.parseFloat(c[2]), 2));
if((value1<=value2)&&(value1<=value3)){ //选出3个value中值最小的
arr1[i][0] = arr[i][0]; //将值赋给新建的数组arr1
arr1[i][1] = arr[i][1];
arr1[i][2] = arr[i][2];
arr1[i][3] = arr[i][3];
sum1_r += Float.parseFloat(arr1[i][1]); //将赋的值相加,后面会用到
sum1_f += Float.parseFloat(arr1[i][2]);
sum1_m += Float.parseFloat(arr1[i][3]);
count1++; //计数
}else if((value2<=value1)&&(value2<=value3)){ //选出3个value中值最小的
arr2[i][0] = arr[i][0]; //将值赋给新建的数组arr2
arr2[i][1] = arr[i][1];
arr2[i][2] = arr[i][2];
arr2[i][3] = arr[i][3];
sum2_r += Float.parseFloat(arr2[i][1]);
sum2_f += Float.parseFloat(arr2[i][2]);
sum2_m += Float.parseFloat(arr2[i][3]);
count2++;
}else if((value3<=value1)&&(value3<=value2)){ //选出3个value中值最小的
arr3[i][0] = arr[i][0]; //将值赋给新建的数组arr2
arr3[i][1] = arr[i][1];
arr3[i][2] = arr[i][2];
arr3[i][3] = arr[i][3];
sum3_r += Float.parseFloat(arr3[i][1]);
sum3_f += Float.parseFloat(arr3[i][2]);
sum3_m += Float.parseFloat(arr3[i][3]);
count3++;
}
}
a[0] = String.valueOf(sum1_r/count1); //强制转换成String,将相加的和除以总个数,获得新的中心点,下同
a[1] = String.valueOf(sum1_f/count1);
a[2] = String.valueOf(sum1_m/count1);
b[0] = String.valueOf(sum2_r/count2); //强制转换成String
b[1] = String.valueOf(sum2_f/count2);
b[2] = String.valueOf(sum2_m/count2);
c[0] = String.valueOf(sum3_r/count3); //强制转换成String
c[1] = String.valueOf(sum3_f/count3);
c[2] = String.valueOf(sum3_m/count3);
iteration++;
}
}
public static void getPrint(){ //打印输出
int j1=0;
int j2=0;
int j3=0;
for(int i=0; i<arr1.length; i++){
if(arr1[i][0] != null){
System.out.println(“客户群1:”+arr1[i][0]+”,”+arr1[i][1]+”,”+arr1[i][2]+”,”+arr1[i][3]);
j1++;
}
}
//上面的算法可能不知道哪里有问题,只有下面加了这句!arr2[i][0].equals(arr1[i][0])才能正常运行,如何找到哪里的算法问题,也请大家多多指正
for(int i=0; i<arr2.length; i++){
if(arr2[i][0] != null&&!arr2[i][0].equals(arr1[i][0])){
System.out.println(“客户群2:”+arr2[i][0]+”,”+arr2[i][1]+”,”+arr2[i][2]+”,”+arr2[i][3]);
j2++;
}
}
for(int i=0; i<arr3.length; i++){
if(arr3[i][0] != null&&!arr3[i][0].equals(arr2[i][0])){
System.out.println(“客户群3:”+arr3[i][0]+”,”+arr3[i][1]+”,”+arr3[i][2]+”,”+arr3[i][3]);
j3++;
}
}
int v = j1+j2+j3;
System.out.println(“客户群1数量:”+j1+”,客户群2数量:”+j2+”,客户群3数量:”+j3+”,总数:”+v);
}
}
数据文件链接:https://pan.baidu.com/s/1Yjgu8Lqehf6VDCK5srRNBQ