這篇博客和美國西雅圖人們使用自行車情況分析與預測(初步)是姊妹篇,是對前一篇博客的延續,更多的背景信息這里不多介紹,可以去以上提到的博客中找到,同樣的所有數據和源代碼都是可以重現的。
和上一篇博客不同的是,這篇博客不在建立模型去預測未來的情況,而是立足于數據,從數據中找出有趣的東西來,換句話說,我們不再像上一篇博客一樣去使用有監督的機器學習方法,取而代之,我們使用無監督的學習方法,類似聚類,把具有相似行為的使用自行車的人們進行聚類,挖掘出一些有趣的玩意。
Part 1: 數據來源
這篇博客和上篇博客使用的數據基本一致,我們可以在github下載,或者我在博客結尾會給出我本人的聯系方式,找我要也行。
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn; seaborn.set() # 這是更高級一點的庫,繪圖更酷炫
data = pd.read_csv(r"E:\研究生階段課程作業\python\好玩的數據分析\SeattleBike-master\Fremont_Bridge.csv",index_col = "Date", parse_dates = True)
data.sample(n = 5) #隨機抽樣5個樣本
data.columns = ["West","East"] #原來的列名太長,蛋疼,改的簡單一些
data.fillna(0,inplace=True) #填充null值,用0填充,同時就地填充:就是直接對data進行填充,不用一系列的賦值之類的操作
data['total'] = data.West + data.East #增加一個新列,計算每個時刻的經過這座橋的自行車總數
![Uploading 5_633120.png . . .]
data.resample('w',how = 'sum').plot()
到目前為止,好像和上篇博客沒有什么不同,處理方法也是一致的,好啦,下面開始放大招了
#因為我們想知道人們在不同日期使用自行車的習慣,我們對數據進行透視
data_pivoted = data.pivot_table(values = ["West","East"], index = data.index.date,columns = data.index.hour,fill_value = 0)
data_pivoted.sample(n = 10)
經過處理后的數據列有48維,為了可視化需要,我們對48列進行降維
from sklearn.decomposition import PCA #使用自帶的pca進行降維
xpca = PCA(n_components = 2).fit_transform(x) #只保留2維
total_trips = data_pivoted.sum(1) #計算每一天的經過自行車總數
plt.scatter(xpca[:, 0], xpca[:, 1], c=total_trips,
cmap='cubehelix')
plt.colorbar(label='total trips');
很明顯,我們可以看出這些數據明顯可以分成兩類,下面要做的就很簡單了,聚類開始登場。首先我們使用kmeans
#首先使用kmeans,聚類的數目為2:
from sklearn.cluster import KMeans
kmeans_model = KMeans(n_clusters=2, random_state=1)
kmeans_model.fit(xpca)
labels = kmeans_model.labels_
#對聚類結果進行可視化
plt.scatter(xpca[:,0],xpca[:,1],c = labels)
plt.colorbar(label='total trips');
果然kmeans表現的還是那么菜,聚類的效果并不完美,下面我們使用高斯混合模型聚類
#使用高斯混合模型,進行聚類
from sklearn.mixture import GMM
gmm = GMM(2, covariance_type='full', random_state=0)
gmm.fit(xpca)
cluster_label = gmm.predict(xpca)
plt.scatter(xpca[:, 0], xpca[:, 1], c=cluster_label);
還是高斯混合模型靠譜啊,多試幾種方法,找出最適合你的方法吧
data_pivoted["Cluster"] = cluster_label
data_new = data.join(data_pivoted["Cluster"],on = data.index.date)
data_new.sample(10)
#對兩個聚類按照時間分別作圖
#data_new_0 #包含cluster為0的所有數據
#data_new_1 #包含cluser為1的所有數據
data_new_0 = data_new[data_new.Cluster == 0]
data_new_1 = data_new[data_new.Cluster == 1]
by_hour_0 = data_new_0.groupby(data_new_0.index.time).mean()
by_hour_1 = data_new_1.groupby(data_new_1.index.time).mean()
by_hour_0[["West","East","total"]].plot()
plt.xlabel("time")
plt.ylabel("mean of bikes")
這個結果相當耐人尋味,我們可以看到,差不多在早上八點左右,自行車數量到達第一個巔峰,然后下午五點左右,自行車數量到達第二個巔峰。是不是這些日子都是工作日呢,大家騎著自行車去上班,換句話說,第一個聚類難道都是工作日。這個問題有待繼續解答,我們再看第二個聚類的情況.
by_hour_1[["West","East","total"]].plot()
plt.xlabel("time")
plt.ylabel("mean of bikes")
和第一個聚類相比,這個結果沒有出現明顯的波峰,大約在下午兩年的時候,自行車數量最多,好吧,你肯定在猜測,這些日子是不是周末呢。大家吃過中飯,騎車出來浪呢。為了搞清楚這些疑問,我們計算每個日期對應的星期幾。
plt.scatter(xpca[:,0],xpca[:,1],c = data_pivoted.index.dayofweek,cmap=plt.cm.get_cmap('jet', 7))
cb = plt.colorbar(ticks=range(7))
cb.set_ticklabels(['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun'])
我們可以得出這樣的結論,周六和周末,人們對自行車的使用有著很大的相似,而周一到周五人們對自行車的使用也很相似,結合前面的聚類結果
但是我們很奇怪的發現一個現象:有一些工作日的人們表現的和周末很相似,這些特別的日子具體是神馬日子的,是不是節假日,另外和其他的工作日相比,周五表現的和周末很曖昧不清,這我們需要思考
另外在工作日的聚類中,我們發現竟然沒有一個非工作日的(至少從圖中沒有發現特例),結果真是這樣嗎,我們需要進一步的使用數據進行分析
days = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun'] #分別對應“dayofweek”:[0,1,2,3,4,5,6]
def get_weekday(index):
return days[index.dayofweek]
data_new_0["weekday"] = data_new_0.index.map(get_weekday)
data_new_0_exception = data_new_0[data_new_0.weekday.isin(["Sat","Sun"])]#在第一個聚類中,找特例,換句話說,就是找出這樣的周六周末,人們對自行車的使用像工作日一樣
len(data_new_0_exception) #結果和我們在上圖可視化的結果一樣,沒有一個周六周末,人們使用自行車像工作日一樣
out:0
沒有一個周末,人們使用自行車和工作日一樣,這也能從側面看出,看來美帝真心不加班啊,不像天朝,加班累成狗。
data_new_1['weekday'] = data_new_1.index.map(get_weekday)
data_new_1_exception = data_new_1[data_new_1.weekday.isin(['Mon', 'Tues', 'Wed', 'Thurs', 'Fri'])]#在第2個聚類中,找特例
len(data_new_1_exception):
out:600
倒是有不少天,人們在工作日的時候和周六周末使用自行車的習慣差不多,我們猜測這些工作日很可能是假期,真的是這樣嗎,我們來驗證一下。
date = set(data_new_1_exception.index.date)
#列出從2012-2016年,美國的所有假期
from pandas.tseries.holiday import USFederalHolidayCalendar
cal = USFederalHolidayCalendar()
holidays = cal.holidays('2012', '2016', return_name=True)
holidays_all = pd.concat([holidays,
"Day Before " + holidays.shift(-1, 'D'),
"Day After " + holidays.shift(1, 'D')])
holidays_all = holidays_all.sort_index()
holidays_all.ix[(date)]
不出意外,這些表現反常的工作日,全部都在假期中。大家都放假了,當然開始騎車去浪了
最后一個問題,為什么周五的數據,可視化的時候,有幾個點表現的特別反常,這幾天究竟發生了什么
fri_day = (data_pivoted.index.dayofweek == 4) #周5為true,其他為false
plt.scatter(xpca[:, 0], xpca[:, 1], c='gray', alpha=0.2)
plt.scatter(xpca[fri_day, 0], xpca[fri_day, 1], c='yellow');
weird_fridays = pivoted.index[fridays & (Xpca[:, 0] < -600)]weird_fridays
weird_fridays
out: Index([2013-05-17, 2014-05-16, 2015-05-15], dtype='object')
果然是,周五的這幾個奇異點,果然有情況,我查閱了一下資料,這三天是一年一度的
自行車日。。。。。果然沒有無緣無故的愛
總結
關于西雅圖市人們使用自行車習慣的數據分析到此就結束了,數據蘊含著很多信息等待我們去挖掘。英文過得去的話,建議直接看原文章,如果有不懂的話,再結合這中文譯文進行參照,如果你對python和機器學習,數據挖掘等感興趣,我們也可以一起學習,一起分享好玩的文章。
QQ 1527927373
EMAIL 1527927373@qq.com