分析學生上網日誌——聚類DBSCAN例項練習
阿新 • • 發佈:2019-01-09
#分析學生開始上網時間和上網時長的模式
#單個學生上網日誌(記錄編號、學生編號、MAC地址、IP地址、開始、停止上網時間、上網時長)
#1.建立工程,引入sklearn相關包
import numpy as np
import sklearn.cluster as skc
from sklearn import metrics
import matplotlib.pyplot as plt
#2.載入資料,預處理資料
#讀取每條資料中的mac地址,開始上網時間,上網時長
mac2id=dict()
onlineTimes=[]
f=open('TestData.txt',encoding= 'utf-8')#注意編碼方式
for line in f:
mac=line.split(',')[2]
startTime=int(line.split(',')[4].split()[1].split(':')[0])#要用int 不能eval
onlineTime=int(line.split(',')[6])#讀取每條資料的mac地址,開始上網時間,上網時長
if mac not in mac2id:#mac2id字典中鍵為mac地址,值為對應mac地址的上網時間和上網時長
mac2id[mac]=len(onlineTimes)
onlineTimes. append((startTime,onlineTime))
else:
onlineTimes[mac2id[mac]]=[(startTime,onlineTime)]
#2.1上網時間聚類,建立DBSCAN,進行訓練,獲得標籤
real_X=np.array(onlineTimes).reshape(-1,2)#變換成n行2列維度的陣列
X=real_X[:,0:1]#提取每行的第一列數,即startTime
db=skc.DBSCAN(eps=0.01,min_samples=20).fit(X)
labels=db.labels_
print('Labels:%s'% labels)#輸出資料被記上的標籤
#計算噪聲資料(標籤為-1)的比例
ratio=len(labels[labels[:]==-1])/len(labels)
#labels[:]==-1生成一個布林陣列,labels[labels[:]==-1]挑出原labels內為-1的元素
print('Noise ratio:{:.2%}'.format(ratio)) #要加:
#計算簇的個數(先把labels變為集合,集合無重複,計算總label個數,減去噪聲label)
n_clusters_=len(set(labels))-(1 if -1 in labels else 0)
print('Estimated number of cluster:%d'%n_clusters_)
#評價聚類效果
print('Silhouette Coefficient:%0.3f'%metrics.silhouette_score(X,labels))
#輸出各簇標號及簇內資料
for i in range(n_clusters_):
print('Cluster',i,':')
print(list(X[labels==i].flatten()))#array.flatten()為摺疊成一維陣列
#直方圖展示,分析結果
plt.subplot(121)
plt.hist(X,24)
plt.xlabel('上網時間')
plt.ylabel('上網時長')
plt.axis([0,25,0,70])
#2.2上網時長聚類,建立DBSCAN,進行訓練,獲得標籤
Y=np.log(1+real_X[:,1:])
db=skc.DBSCAN(eps=0.14,min_samples=10).fit(Y)
labels=db.labels_
print('Labels_Y:%s'%labels)
ratio=len(labels[labels[:]==-1])/len(labels)
print('Noise ratio:{:.2%}'.format(ratio))
n_clusters_=len(set(labels))-(1 if -1 in labels else 0)
print('Estimated number of cluster:%d'%n_clusters_)
print('Silhouette Coefficient:%0.3f'%metrics.silhouette_score(Y,labels))
#統計每一個簇內的樣本個數,均值,標準差
for i in range(n_clusters_):
print('Cluster',i,':')
count=len(Y[labels==i])
mean=np.mean(real_X[labels==i][:,1])
std=np.std(real_X[labels==i][:,1])
print('\t number of sample:%d'%count)
print('\t mean of sample :%.2f'%mean)
print('\t std of sample :{:.2f}'.format(std))
plt.subplot(122)
plt.subplots_adjust(wspace=0.3)#調整subplots之間橫向間距,縱向用hspace
x=np.linspace(0,len(labels),len(labels))
plt.plot(x,real_X[:,1])