这篇博客和美国西雅图人们使用自行车情况分析与预测(初步)是姊妹篇,是对前一篇博客的延续,更多的背景信息这里不多介绍,可以去以上提到的博客中找到,同样的所有数据和源代码都是可以重现的。
和上一篇博客不同的是,这篇博客不在建立模型去预测未来的情况,而是立足于数据,从数据中找出有趣的东西来,换句话说,我们不再像上一篇博客一样去使用有监督的机器学习方法,取而代之,我们使用无监督的学习方法,类似聚类,把具有相似行为的使用自行车的人们进行聚类,挖掘出一些有趣的玩意。
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个样本
随机抽样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
果然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);
9.png
还是高斯混合模型靠谱啊,多试几种方法,找出最适合你的方法吧
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")
12.png
和第一个聚类相比,这个结果没有出现明显的波峰,大约在下午两年的时候,自行车数量最多,好吧,你肯定在猜测,这些日子是不是周末呢。大家吃过中饭,骑车出来浪呢。为了搞清楚这些疑问,我们计算每个日期对应的星期几。
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'])
13.png
我们可以得出这样的结论,周六和周末,人们对自行车的使用有着很大的相似,而周一到周五人们对自行车的使用也很相似,结合前面的聚类结果
但是我们很奇怪的发现一个现象:有一些工作日的人们表现的和周末很相似,这些特别的日子具体是神马日子的,是不是节假日,另外和其他的工作日相比,周五表现的和周末很暧昧不清,这我们需要思考
另外在工作日的聚类中,我们发现竟然没有一个非工作日的(至少从图中没有发现特例),结果真是这样吗,我们需要进一步的使用数据进行分析
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');
15.png
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
网友评论