新闻中心
XX大学 共享单车数据分析报告(大学校园共享单车运营数据)
以下内容为本人在数据挖掘学习过程中的原创报告,欢迎批评指正,转载请联系。
1问题定义
在开始本实验之前,注意到网上有很多关于共享单车的数据分析,但分析大多停留在简单统计层面。计划着眼学校内的共享单车,通过获取获取该区域内的单车数据,利用一些数据挖掘算法从数据中发现一些信息,希望对单车运营者或者同学提出一些建议或者出行指导。
2数据获取
2.1数据需求
由于学校内的共享单车品牌只有哈啰单车,本实验需要获取哈啰单车在学校内的车辆分布数据。因为车辆数据需要积累一定时间长度才具有研究价值,本实验计划获取一个工作日24小时的单车分布数据。
2.2 数据来源
2.2.1哈啰出行APP
首先尝试对哈啰出行APP进行抓包,原以为APP只会对请求进行一些加密,但最后在抓包记录中却没有发现明显的车辆数据请求。
抓包显示在一个高德地图的点标注API调用后,APP界面出现了车辆信息。但在此请求中没有出现任何关于车辆位置的信息,在此之前的请求也没有任何关于车辆位置的信息。
经过更换系统平台、重复抓包、仔细核对后,依然没有找到突破口。结合没有在网络上查找到任何关于哈啰单车爬虫的信息,猜想哈啰单车可能采取了一些反爬措施(如自定义协议)等。
2.2.2哈啰单车小程序
对APP获取数据失败后,进一步分析网络上关于摩拜单车和ofo单车的数据爬取介绍文章。发现,作者们都是通过对摩拜单车和ofo单车的微信小程序进行抓包,获取数据,而非直接爬取APP。
微信小程序作为第三方服务平台,开发受限,各种服务支持应该都是通过相应API提供的,但哈啰出行并没有相应的微信小程序。
于是尝试对支付宝中的哈啰单车小程序进行抓包,结果和哈啰出行APP的情况如出一辙:没有明显的数据获取API调用,在请求一个高德地图API后出现了车辆信息。
2.2.3 H5服务入口
最终,在不断的检索中,于网络跳转间发现哈啰出行提供了一个较为隐蔽的h5服务。该页面在搜索引擎中很难检索到。
从哈啰单车的H5服务入口,可以分析出其工作流程:①在未登录的情况下,可以利用API获取某个坐标周围半径500米内的少量单车信息;登陆后则能显示出半径500米内的所有单车信息。②在登陆后,10秒内的请求不能够超过三次,否则账号会被封禁。
2.3数据抓取策略
了解工作流程后,可以制定对应的爬取策略:
1. 通过模拟登录,获取登录后的token并保存,创建token池。
2. 对学校的地理区域采用矩形近似,将该矩形划分成若干个边长为500米的小方块,通过查看方块顶点坐标周围的车辆信息有效获取校区内所有车辆信息,并做到每次获取最小重叠。
3. 每次获取车辆信息时,从token池中顺序采用token,以降低token访问频率,防止被封。
4. 不断抓取单车信息,实现每15秒抓取完成一次全校车辆信息,每次抓取后休眠105秒,连续抓取24小时。
3数据处理
3.1数据概况
抓取到的数据大小为82.5M,记录数为1310069,原始数据格式如图1所示:

第一列为抓取时间,第二列为单车编号,第三列和第四列分别为经度和纬度。
3.2数据去重
从理论上来说,抓取的数据不会存在重复。但在实际操作过程中,我为了方便起见,时间只精确到了分钟;并且由于网络不稳定因素,抓取时的速度可能存在波动,导致有少部分单车在同一分钟内被抓取了两次。这会给后面定位单车在某一时刻的位置带来干扰,所以需要进行去重操作。
本实验针对时间和单车编号字段、保留最后一次的记录进行去重,共删除985行重复数据。
3.3构建观察矩阵
本实验需要根据原始数据计算出每辆车的骑行时间,根据原始数据中的time和bikeno字段,我可以构建一个关于time和bikeno的矩阵,形如图2:

其中,columns为观察窗口的观察时间点,index为观察窗口内出现的单车编号。
记Matrix为该矩阵,i为观察窗口内的某辆单车编号,j为观察窗口内的某个观察时间点。
Matrix[i,j]表示编号为i的单车,在观察时间点为j时的观察状态。其中,1表示available,0表示available。
观察状态status的计算方式可由某一时刻校园内的所有可用车辆信息得到:
1. 记观察窗口内的所有车辆为Ω;
2. 记观察窗口内的一辆单车为i;
3. 记观察窗口内的一个观察时间点为j,观察时间点内的所有车辆为ωj;
4. 若i∈ωj,那么status=1,否则stauts=0。
为了描述方便,以下使用观察点代指观察时间点、状态代指观察状态。
3.4发现骑行
本实验需要获取每辆单车在观察窗口内的骑行信息,即找到开始骑行的时间、开始骑行的经纬度和结束骑行的时间、结束骑行的经纬度。
对应到观察矩阵中,即对于每一行,需要找到该行中,状态由1转为0、以及由0转为1的观察点。需要注意的是,对于观察窗口边界,状态为0的骑行不参与考虑,即第一个观察点和最后一个观察点状态应为1,否则虽然在观察边界车辆状态为0可以表示不可用(骑行),但超出了观察边界,不能作为本实验的研究对象。
为了增强数据的可读性,该部分本实验采用python中的字典类型和列表类型进行存储,示例如图3:

3.5推算路线
本实验还包括对骑行路线的研究,但这些信息不能通过公开渠道获得。我对用户骑行行为进行推断,假设用户选择的骑行路线选择都是最优的,这样可以通过计算起始点间的骑行路线来近似模拟用户的骑行行为。
因为哈啰单车采用的是高德地图,为了保证实验数据的精确性,在骑行路径规划方面,本实验选择了高德地图作为API提供方。
高德地图的骑行路径规划功能十分丰富,返回信息包括距离、骑行用时、路径内容等,其中路径内容包含距离、时间、经纬度点集等。具体返回参数可查看高德地图API网站;https://lbs.amap.com/api/webservice/guide/api/direction#t8
本实验通过提取路径中的关键点的经纬度集合,将骑行路线近似为一个点集。此外,通过路线的估计时长与观察到的骑行时长对比,可以为推算路线的置信度提供参考。路线长度和预估时长也将作为实验的研究对象。
4数据分析
4.1建立聚类模型
实验的目标在于发现隐藏在哈啰单车数据之下的信息,由于实验数据不具有标签性,故选择聚类分析进行数据挖掘。首先,本实验选择骑行开始时间、骑行结束时间、实际骑行时间、骑行距离进行聚类分析。
在进行聚类分析前,仍需要对数据进行进一步清洗:
1. 筛选骑行数据中实际骑行时间>10秒,骑行距离大于10米的记录,以减轻噪声点对聚类结果的干扰;
2. 将骑行开始时间、结束时间映射到0-24,以满足Kmeans++对于数据格式的要求;
3. 为了消除量纲的影响,本实验对数据进行z-score标准化处理。
在聚类算法的选择方面,本实验选择Kmeans++算法,该算法是Kmeans算法的改进,具有时间复杂度、空间复杂度低的特点,适合处理数据规模较大的数据集。相对于Kmeans算法, Kmeans++改进了一开始对数据集中心点的选择:假设已经选取了n个初始聚类中心(0<n<K),则在选取第n+1个聚类中心时,距离当前n个聚类中心越远的点会有更高的概率被选为第n+1个聚类中心。这一改进直观有效地减小了Kmeans由于初始中心点随机选择导致陷入局部最优解的结果。
在确定聚类个数时,本实验选择以误差平方和(Sum of the Squared Error,SSE)作为评价标准,SSE描述的是各样本与质心的离散程度,SSE越小,聚类效果越好。
本实验采用循环的方式,观测不同聚类个数情况下,SSE的大小。结果如图4所示:

由clusters-ESS折线图可以看出,在clusters=4时,斜率显著变小。可以认为进一步增加聚类个数对聚类效果的提升有限。所以本实验的最佳聚类个数是4。
利用matplotlib对聚类后的结果分别进行三维可视化,由于骑行开始时间、骑行结束时间和骑行时长是线性关系,在空间中的存在形态为平面,对实验研究没有帮助,此处仅作出骑行开始时间、骑行结束时间和骑行距离以及骑行开始时间、骑行距离和骑行时长的图像。图像如图5、图6所示:

为了描述方便,以下将骑行开始时间、骑行结束时间、骑行距离、骑行距离分别用start_time、end_time、distance、duration表示,简记为st、et、di、du。
4.2模型基本情况解读
由图5和图6,可以看到st-et-di和st-di-du聚类结果类间划分清晰,有明显的边界,由图5可得:
1. 样本点仅存在于一半的立体空间中,这是因为骑行结束时间总是晚于骑行开始时间。
2. 位置更高的点,即骑行距离更长的点,均距et=st平面有一定距离。距et=st平面越远,即表示结束时间距开始时间越远,符合骑行距离长需要骑行时间长的必要条件。但在图中,反之,距et=st平面越远的点,却并不一定位置更高,也就是说骑行时间长并不一定骑行距离长,这点我也将在后面讨论。
3. 大部分的样本点都距et=st平面较近,也距st-et平面较近。这表明大多数用车情况下,骑行时间和距离都不长。
将图6 st-di-du散点图旋转一定角度后,得图7。由图7可得,虽然绝大多数样本点都属于骑行时长、骑行距离均较短的类别,但骑行时长和骑行距离并没有特定的关联,甚至出现了骑行时长很短,但骑行距离较长的异常点。

总体看聚类形成的四个簇:
1. 从骑行时长上看:紫色、绿色、黄色簇的骑行时间都在1.8小时以内,而蓝色的骑行时间均在1.8小时以上。
2. 从骑行距离上看:紫色和绿色簇的骑行距离在1500米以内,黄色簇的骑行距离大于1500米,蓝色簇的骑行距离从100米到3100米都有分布,但更多集中在100-1000米。
3. 从时间分布上看:蓝色簇的分布稀疏有致,骑行开始时间绝大部分都集中在5点以后、18点之前。
由上述分析,可以总结出四个簇的基本特征:
1. 黄色簇骑行开始、结束时间分布较广,持续时间较短,骑行距离较长,速度很快;
2. 紫色簇骑行开始、结束时间均在14:00-24:00之间,持续时间和距离较短,速度适中;
3. 绿色簇骑行开始、结束时间均在0:00-15:00之间,持续时间和距离较短,速度适中;
4. 蓝色簇骑行开始、结束时间分布较广,持续时间不确定,骑行距离不等,但多数较短,速度最慢。
可以看出,蓝色簇的表现较为异常。
4.3异常簇解读
蓝色簇表现出明显异于其他簇的特性,从骑行速度和骑行时间来看,也显然不符合正常的骑行特征。
结合本实验的观察方式,推测这些车辆在某时刻被骑行,接着脱离了观察范围,最后又进入了观察范围。脱离观察范围时,车辆将一直处于unavailable状态(无论此时车辆是否真的被占用),被标记为占用。当车辆进入观察范围,且被锁住时,则恢复available状态。于是,该过程仅被标记为一次骑行。
脱离观察范围的情况可能有两种:
1. 车辆在两个观察点之间发生了结束骑行和开始骑行。由于本实验每次抓取约耗时10-40秒,记为s,间隔时间取120-s,即每个抓取周期为120秒。若车辆在两个观察点之间(即120秒内),结束了一次骑行并开始了新的骑行,则两次记录可能会被判定为一次骑行。
2. 车辆驶出了观察的地理范围。若果车辆驶出了学校,结束了骑行,一段时间后再次开始骑行,并驶入了学校,则会被判定为一次骑行。
由于蓝色簇的骑行时间基本都在1.8小时以上,并且校园内车辆较为充足(发生刚停车立即被骑行的可能性较小)、同学单次骑行时间较短(连续发生多次停车后立即被骑行的可能像较小),所以第一种情况导致的可能性很小。同时,蓝色簇的骑行开始时间大部分在5至18点、骑行结束时间大部分在10到23点,与同学们的生活习惯相符合:同学们早晨骑车出校门,接近中午时陆续有同学返回,从校门骑车进学校。出去的时间从早5点持续到晚6点左右,回来的时间从10点持续到23点左右。
因此,本实验认为蓝色簇代表出校骑行。
4.4出校骑行分析
由蓝色簇的一些特征属性可以分析出以下信息:
1. 分布的稀疏性说明工作日骑车出校门的同学是小部分;
2. 蓝色簇骑行距离范围大约在100到3100米,绝大多数集中在1000米以下(此时的骑行距离代表的是骑行开始点与结束点的距离)。可以推断出,骑行过程中出校的车辆,其出发点与回校的终点大多数都十分接近(距离在1000米之内),即使用场景较为稳定。
大多数车辆会由人口密集地出发,又回到人口密集地,而清晨和夜晚校内人口密集地彼此之间又比较接近,如第一、二组团,所以只有少部分车辆的出发点和终点相距大于1000米。
接着,我观察校园内可用单车总数量与时间的变化,作出图8:

可以看到:
1. 总体上,学校内的可用车辆总数呈波动状,在10点时达到最低谷,在18点左右达到次低谷,这表示同学们的用车的高峰集中在10点和18点。
2. 接近24点时,校园内的可用车辆总数小于0点时的数量,这说明校园车辆处于流失状态,即驶出校园的车辆数大于回流车辆数,达到150辆之多。
为了进一步研究单车出校情况,避免校内出行高峰对观测产生的影响,本实验进一步对不同时间的出校车辆数进行观测。我将车辆的判定条件设置为骑行时长大于1.8小时(约6000秒),结果如图9:

可以看到,出校骑行的高峰分别出现在8点、10点、12点、14点和18点左右。
推测不同的出校骑行高峰分别代表了不同的学生群体或者出行场景,8点左右的骑行可能代表了实习同学的通勤场景,10点左右的高峰体现了出校办事、游玩的同学的需求,14点和18点的出校需求可能表示了同学们的社交需求。这几类出行场景较为固定,工作日的出校出行需求应当较为稳定。但是由于流失现象显著存在,会造成单车的显著分布不均,这对于单车运营管理者来说,增加了管理调度的难度。
4.5骑行时长与骑行距离关系解读
上文有提到,骑行时长与骑行距离间并未显示出显著的相关性,接下来,我将进一步探索分析这方面的内容。
4.5.1基本关系分析
首先,做出所有类别的骑行时长直方图,如图10:

可以看到,除蓝色簇外,其他三个簇骑行时长基本都集中在1000秒以下。
其次,做出骑行距离与骑行时长的散点图,如图11:

可以看到,各类骑行的骑行距离与骑行时间的确没有显著的线性关系。这与我的认知略有不符合,通常,我认为骑行距离与骑行时间呈显著趋势。
考虑到长骑行时间可能带来的误差和干扰,本实验再对骑行时长在1000秒(约16.7分钟)以下的骑行记录进行骑行时长-骑行距离散点图描绘,如图12:

可以看到,骑行时长与骑行距离仍无显著关系。对骑行时长在1000秒以下的记录中的骑行开始时间、骑行时长、骑行距离进行相关性分析,结果如图13:
图13相关系数矩阵1由图13可知,骑行时长与骑行距离的相关系数为0.311887,相关系数较低。
4.5.2原因解读
骑行距离与骑行时长并未呈现显著相关性的原因可能有:
1、单车虽一直处于开锁状态,但并非一直处于骑行状态。我在校园内也能偶尔观察到宿舍楼下或超市门口并未关锁的单车,这是同学们出于宣誓单车主权心理(担心锁车会被他人扫码骑走)的行为。
2、高峰期用车时,前人停车,后人用车的时间点正好在观察点间隔期内,被判定为同一次骑行。
3、骑行者折返骑行或者绕路骑行。
4.5.3原因验证
注意到之前对校园内可用车辆数进行过折线图描绘,为了验证猜想2,本实验选择骑行次数较低的13:00-13:30间的样本数据进行相关性分析(避免高峰期干扰),同样地,限定骑行时长在1000秒内,结果如图14。
图14 相关系数矩阵2可以看到,骑行时长与骑行与骑行距离的相关性是0.426849,较之前有一定提升。
再次作散点图:
图15 骑行时长1000秒内、骑行时间在13-13:30不同类别的骑行距离-骑行时长散点图可以看到,紫色簇也已经被过滤了。绿色簇和黄色簇呈现出了一定的趋势,黄色簇的distance/duration的斜率较为陡峭(黄色簇的纵轴坐标值更大),而绿色簇则较为平缓。所以黄色簇的样本点骑行速度更快,绿色簇的则较为缓慢。
骑行次数较少的时段相比高峰期,骑行距离与骑行时间的相关性更大,有理由猜想在出行高峰期,同一辆单车在观察间隔期内被停下又骑行的概率大大提升,会产生大量误判(将两人或更多人的骑行算做一次骑行),造成“一次骑行”中有折返现象,从而模糊骑行距离与骑行时间的关系。
4.5.4正常与异常单次骑行识别
除了高峰期之外,较长的时间也可能带来误判率的提升。以骑行距离和骑行时长的相关系数作为误判率的表征,分别对13:00-13:30和全天时刻,计算不同骑行时长下的相关系数,如图16和图17所示:
图16 13:00-13:30 相关系数随骑行时长变化曲线图17 全天时刻 相关系数随骑行时长变化曲线由图16、图17综合可知,相关系数的最高点在400秒至600秒之间,由600秒后的弱相关性可以推断,正常单次骑行的时间落在600秒内的可能性最大。
同时,骑行时长在600秒内的骑行记录,平均速度为2.8m/s,接近正常骑行速度(正常骑行速度参照高德导航,为3.6m/s)。以下用正常骑行代表骑行时间在600秒内的骑行。
经统计得出,骑行时间在600秒内(包括600秒)的记录数为9653,占全部记录数20113的47.9%。而出校骑行,即骑行时长在1.8小时(约6000秒)以上的记录数为4487。为了方便计算,取50%作为该概率近似值。那么,由于观察间隔造成多次正常骑行被判定成一次出校骑行的概率为0.5^10≈0.00098。这个概率很小,所以出校骑行的判断依据仍然成立。
同理,骑行时间在1800秒内,且由正常骑行构成的可能性为0.5^3≈12.5%。1800秒以上的骑行概率过低,认为大部分是非正常骑行。下面,对600-1800秒的骑行记录进行探索,观察其骑行特征:
①骑行时长在600秒和1800秒内的记录数为2267条。
②骑行速度在正常步行速度和两倍正常单车速度之间的记录数为709条。其中步行速度参照高德导航,为0.9m/s。
③骑行速度大于两倍正常单车速度的的记录为0条。
④骑行速度在正常步行速度以下的记录数为1558条。
⑤骑行时长在600-1800秒内的平均速度为0.8m/s,远低于正常单车速度。可以推测骑行时长在600秒到1800秒内的骑行记录大部分属于异常骑行。
作出正常骑行和异常骑行随时间的变化曲线,如图17、18:
图18正常骑行数量-时间变化曲线 图19 异常骑行数量-时间变化曲线由折线图可以看出,异常骑行和正常骑行的高峰时刻基本吻合。
在出行高峰期,车辆利用率高,车辆结束骑行和开始骑行的时间点落入观察间隔期的概率更大,也说明此处的车辆流转率高,留存率较低,可用车辆数紧张。对比正常出行和异常出行的高峰差,即图17有高峰,图18没有高峰的地方,可以找到车辆流转度高地(此时从能捕捉到的正常骑行中catch到了一个出行高峰,但是有更多正常骑行周转落在了观察间隔点,以至异常骑行中捕捉到的数量不够多,说明此时车辆流转度很高)。
发现一个车辆流转率高的时刻为16时左右。具体时刻为15.867220时,即15时52分。将该时刻前后5分钟内骑行结束的终点和开始骑行的起点进行标记,可以看到流转热点,如图19。
图19 流转热点经纬度散点图可以看到出行高峰前后5分钟内,正常骑行记录的终点和起点重合度非常高。这些重合的点即流转热点,车辆留存度低,车辆运营管理者需要在该时刻前对这些流转点进行车辆补充。将这些点在地图上标出,如图20所示:
图20 15:52流转热点地图标注图中绿色的点即15时52分左右车辆流转度高的点,主要集中在生科楼、一组团宿舍区、仙1仙2教学楼和10食堂。
不同时刻的流转热点可能不同,将车辆从流转度低的点调度到流转热点能够有效提升车辆利用率。
对全天时间内的正常骑行(骑行时长在600秒内)的起终点在地图上标注,观察宏观范围上的车辆流转情况,如图21所示:
图21 全天流转热点地图标注图中蓝色的点表示流出,黄色的点表示流入。可见从宏观上,绝大多数地区流转情况良好,这说明本校单车调度人员的工作成效良好。但也可以看到部分区域仍只有流入或流出,这说明局部区域的流转情况仍有待提升。
5数据分析结果总结与应用
5.1出校骑行
工作日内,学校内的出校骑行有着较为固定的出行场景和稳定的车辆需求。但是由于流入流出差的存在,每天约有150辆车辆流出校园。由于校园外的车辆利用率远低于校园内,并且校园外的管理调度难度远大于校园内,这对于单车的运营管理者来说是一份不小的工作量。
注意到近期哈啰单车投放了大量校园单车,校园单车限制了单车的骑行范围为校园内,超出区域则要收取调度费。说明哈啰单车已经注意到了这一现状,采取了一定措施来在一定程度上减轻了校园车辆的流失。
但考虑到同学们不同出行场景的需求,将现有单车都更换成校园单车会对部分同学的出行造成不便,为了平衡运营管理难度与用户体验,可以采取以下措施:
①在校门处投放一定数量普通单车,5分钟内由校园车辆换骑至普通车辆,延续校园车辆的使用时间进行计费,不另收费用。例如车辆收费标准为每半小时1元,一同学骑行校园车辆x(x<30)分钟至校门,结束骑行,收费1元。5分钟内更换骑行普通车辆出校,则此次骑行30-x分钟内不收费,30-x分钟后再正常计费。
②采取激励措施,例如从校外骑到校内某些区域免费或者给予小额红包等,鼓励同学们将骑到校园外的车辆骑回校园内以减轻运营者的劳动量,促进校内外车辆正常流转。
5.2流转热点
流转热点在本实验中是指某时刻某范围内一辆单车停下不久后就被骑走的情况,说明某时刻某范围内的可骑行车辆数量远小于需求数量。
流转热点的存在是由骑行的不对称性造成的,这包含了两个维度的信息:时间和地点。
从宏观上来看,校园内大部分区域的大部分区域都是绿色,这说明该地区一天内的流转状况良好,但是不同时刻的流转热点可能不同,如果只关注一天内区域间的流转情况,则很多潜在的骑行会因为某时刻车辆数量不足而无法开始,例如本实验上文提到的15时52分左右的一个流转热点。
综上,运营管理者不仅仅需要从宏观上关注车辆区域间的流动数量和从微观上关注车辆骑行的潮汐方向,还需要两者结合起来,关注两次潮汐间的连接点(即流转热点)的车辆数量、使用率等情况,以获得一定的统计数据,并根据这些统计数据对车辆调度进行适时调整,将流转点的车辆数量和使用率维持在一个合理的水平。
此举能大幅提高单车的日均骑行次数,但对运营者的调度能力也提出了很高的要求,可以先向几个大的流转热点进行车辆调度,以有效提升车辆利用率,再根据调度能力做适当调整。
6总结
本实验从抓取数据到总结分析,共耗时半月有余。期间经历了分析方向的迷茫、模型结果的出乎意料等困难,尝试了ArcGIS、Echarts、和高德可视化分析等工具。
最初我的想法很简单,试图就从数据中发现一些显而易见的规律,而对与日常认知不符的信息束手无策。最终,本实验只发现一条显而易见的规律就是:数据挖掘是为了发现隐藏在数据背后的信息,而这些信息并不是一眼就能看出的,需要对模型结果进行观察、解读、思考和验证。
分析之后,再将发掘到的信息结合具体业务场景进行应用,这才是实现了数据挖掘的完整闭环。
相关链接:
爬虫代码:https://github.com/flycattt/ttbike-spide (由于本人注销了百度账号,数据和代码已更新于此链接dataset下)