基于python的transbigdata实现出租车轨迹数据分析与可视化

来源:互联网转载 | 更新日期:2023-09-10 02:13:30

TransBigData是一个为交通时空大数据处理、分析和可视化而开发的Python包。TransBigData为处理常见的交通时空大数据(如出租车GPS数据、共享单车数据和公交车GPS数据等)提供了快速而简洁的方法。TransBigData为交通时空大数据分析的各个阶段提供了多种处理方法,代码简洁、高效、灵活、易用,可以用简洁的代码实现复杂的数据任务。转自同济大学余庆博士的文章:点击跳转

应专业选修课《数据分析与可视化》的期末考核,本人参考了@小旭学长的文章:点击跳转 

本文根据上述文章,对该项目进行了一些代码上的修改(在一些可能报错的地方进行了修改),以及增加了对代码的解释以及图文介绍,并且增加了上海的出租车轨迹数据。

本项目作为课程设计参考,个人感觉本项目在最后的呈现效果上十分出色。该项目使用jupyter notebook开发环境。

项目地址:https://gitee.com/scaukzh/visualization

话不多说,直接看项目。

数据:

①出租车轨迹数据集

来源:https://people.cs.rutgers.edu/~dz220/data.html

介绍:该数据源自国外大学一名助理教授,包含了深圳市2013.10.22一天中大约600多辆出租车的轨迹数据,数据包含的信息依次为出租车ID,时间,纬度,经度,占用状态,速度;入住状态:1-乘客和0-乘客。数据一共大约54w条。

VehicleNumTimeLngLatOpenStatusSpeed01234...544994544995544996544997544998
3474520:27:43113.80684722.623249127
3474520:24:07113.80989822.62739900
3474520:24:27113.80989822.62739900
3474520:22:07113.81134822.62806700
3474520:10:06113.81988522.647800054
..................
2826521:35:13114.32150322.709499018
2826509:08:02114.32270122.68170000
2826509:14:31114.33670022.69010000
2826521:19:12114.35260022.72839900
2826519:08:06114.13770322.62170000

544999 rows × 6 columns

补充:我在项目中补充了一个上海的数据集,该数据集是香港科技大学智慧城市研究小组共享的数据集,包含上海市2007年02月20日单日若干辆出租车的轨迹数据。

②地图数据

地图采用json格式,这个地图数据用于标明深圳区域的范围,在后期进行绘图以及数据处理的时候都有作用。

代码部分:

一、第三方包和数据集的导入

1.第三包的导入

import transbigdata as tbd import pandas as pd import geopandas as gpd import matplotlib.pyplot as plt

使用pip命令直接装transbigdata和geopands包可能会失败。不过transbigdata我已经放在项目中去了,大家直接调用即可。geopands比较容易装,这里就不详细讨论了。

2.读入出租车GPS轨迹数据

data = pd.read_csv('D:/code_for_school/visualtaxi/gps_data/shenzhen_taxi_gps.csv', header=None)#修改自身路径即可 data.columns = ['VehicleNum', 'Time', 'Lng', 'Lat', 'OpenStatus', 'Speed'] data.head() #head函数其中一个默认参数为5,故只返回头5条数据 VehicleNumTimeLngLatOpenStatusSpeed01234
3474520:27:43113.80684722.623249127
3474520:24:07113.80989822.62739900
3474520:24:27113.80989822.62739900
3474520:22:07113.81134822.62806700
3474520:10:06113.81988522.647800054

3.读入深圳市地图数据

# Read the GeoDataFrame of the study area sz = gpd.read_file(r'D:/code_for_school/visualtaxi/geo_data/sz.json')#修改自身路径即可 sz.crs = None sz.head() centroid_xcentroid_yqhgeometry01234
114.14315722.577605罗湖POLYGON ((114.10006 22.53431, 114.10083 22.534...
114.04153522.546180福田POLYGON ((113.98578 22.51348, 114.00553 22.513...
114.27020622.596432盐田POLYGON ((114.19799 22.55673, 114.19817 22.556...
113.85138722.679120宝安MULTIPOLYGON (((113.81831 22.54676, 113.81948 ...
113.92629022.766157光明POLYGON ((113.99768 22.76643, 113.99704 22.766...
sz.plot()

二、数据处理

1.剔除掉超出深圳地图范围的数据

# Data Preprocessing # Delete the data outside of the study area data = tbd.clean_outofshape(data, sz, col=['Lng', 'Lat'], accuracy=500) #剔除超出研究区域的数据 data.head(20) VehicleNumTimeLngLatOpenStatusSpeed012345678910111213141516171819
3474520:27:43113.80684722.623249127
2736809:08:53113.80589322.624996049
2299810:51:10113.80693122.624166154
2299810:11:50113.80594622.625433043
2299810:12:05113.80638122.623833060
2239612:14:28113.80660222.623949145
3243608:15:34113.80646522.624166050
3243608:15:04113.80705322.62635000
3243608:15:19113.80625222.625933022
3243608:14:49113.80705322.62633300
3243618:10:57113.80688522.622967050
3243618:10:27113.80645022.626083036
3243618:35:15113.80668622.623632129
3243618:10:42113.80598422.624683041
2737318:58:43113.80596922.624983042
2737308:42:34113.80711422.623211061
3191009:49:56113.80680122.626200025
3516100:43:41113.80703022.622833151
3516100:43:25113.80709822.624184154
2341120:20:06113.80654922.623550056

如此一来,那些不在深圳市版图中的数据就被我们剔除掉了。

2.对数据按照车辆编号和时间顺序排好

# Delete the data with instantaneous changes in passenger status data = tbd.clean_taxi_status(data, col=['VehicleNum', 'Time', 'OpenStatus']) #删除出租车数据中载客状态瞬间变化的记录,这些记录的存在会影响出行订单判断。 #判断条件为:如果对同一辆车,上一条记录与下一条记录的载客状态都与本条记录不同,则本条记录应该删去 #实际上就是按照编号和时间顺序将数据排好 data.head(30) VehicleNumTimeLngLatOpenStatusSpeedLONCOLLATCOL452072444077444078444075444079444073444074444076452073446704422019422218426967443922443923422292422295422291443991443987
2239600:00:29113.99671922.6933331208165
2239600:01:01113.99551422.6950321348166
2239600:01:09113.99543022.6957661418166
2239600:01:41113.99536922.696484108166
2239600:02:21113.99543022.6966501178166
2239600:03:01113.99493422.6978840238166
2239600:03:41113.99268322.6973500188166
2239600:04:21113.99234822.6967330368166
2239600:05:01113.99299622.693632028165
2239600:05:41113.98925022.6930830568065
2239600:06:21113.98636622.6910000487965
2239600:07:41113.98874722.6854500168063
2239600:08:21113.98958622.6817490438063
2239600:09:01113.98601522.681583007963
2239600:09:41113.98648122.6803320477962
2239600:10:21113.98829722.6764160318061
2239600:11:01113.99160022.6775170418062
2239600:11:09113.99214922.6773170338062
2239600:11:41113.99340122.6743680318161
2239600:11:49113.99344622.674217008161

可以看到编号相同的数据是相邻并且是以时间推进排序的。

3.将数据按照经纬度进行栅格化

栅格化的意思就是把每个数据按照经纬度分到不同位置的格子上

# Data gridding # Define the bounds and generate gridding parameters bounds = [113.6, 22.4, 114.8, 22.9] params = tbd.area_to_params(bounds, accuracy=500) params #(113.6, 22.4, 0.004872390756896538, 0.004496605206422906) #栅格参数(lonStart,latStart,deltaLon,deltaLat),分别为栅格左下角坐标与单个栅格的经纬度长宽 # Mapping GPS data to grids data['LONCOL'], data['LATCOL'] = tbd.GPS_to_grid(data['Lng'], data['Lat'], params) data.head() VehicleNumTimeLngLatOpenStatusSpeedLONCOLLATCOL452072444077444078444075444079
2239600:00:29113.99671922.6933331208165
2239600:01:01113.99551422.6950321348166
2239600:01:09113.99543022.6957661418166
2239600:01:41113.99536922.696484108166
2239600:02:21113.99543022.6966501178166

这一部分完成,我们就已经将数据划分在不同的栈格里了。

4.计算每个栅格中的数据个数

# Aggregate data into grids #python中groupby函数主要的作用是进行数据的分组以及分组后地组内运算! datatest = data.groupby(['LONCOL', 'LATCOL'])['VehicleNum'].count().reset_index() # Generate the geometry for grids datatest['geometry'] = tbd.grid_to_polygon([datatest['LONCOL'], datatest['LATCOL']], params)# Change it into GeoDataFrame # import geopandas as gpd datatest = gpd.GeoDataFrame(datatest) datatest.head() #计算出每个栅格里的出租车数量(不按时间,是一天数据中所有的点) LONCOLLATCOLVehicleNumgeometry01234
36633POLYGON ((113.77297 22.68104, 113.77784 22.681...
36642POLYGON ((113.77297 22.68553, 113.77784 22.685...
36651POLYGON ((113.77297 22.69003, 113.77784 22.690...
36661POLYGON ((113.77297 22.69453, 113.77784 22.694...
36678POLYGON ((113.77297 22.69902, 113.77784 22.699...

LONCOL代表经度上第几个栈格,LATCOL代表维度上第几个栈格,VehicleNum表示了这个栈格中数据的数量,可用于后面进行GPS轨迹热力图的绘图。

5.OD订单的处理

①将各个数据转化成OD数据(每一个数据代表状态)

载客状态无非就两种状态,即(载客-空载-载客)和(空载-载客-空载)。

# Extract taxi OD from GPS data #OD形成就是每一个订单都算一个OD行程,每一行代表一个OD行程 #stime代表出发时间,slon和slat是出发的经纬度 #etime代表结束时间,elon和elat是结束的经纬度 # ID是订单顺序号 oddata = tbd.taxigps_to_od(data,col = ['VehicleNum', 'Time', 'Lng', 'Lat', 'OpenStatus']) oddata VehicleNumstimeslonslatetimeelonelatID42707513130141741737616021768...175519212092119041224103170962
2239600:19:41114.01301622.66481800:23:01114.02140022.6639180
2239600:41:51114.02176722.64020000:43:44114.02607022.6402661
2239600:45:44114.02809922.64508200:47:44114.03038022.6500172
2239601:08:26114.03489722.61630101:16:34114.03561422.6467173
2239601:26:06114.04602122.64125101:34:48114.06604822.6361834
........................
3680522:49:12114.11436522.55063222:50:40114.11550122.5579835083
3680522:52:07114.11540222.55808323:03:12114.11848422.5478675084
3680523:03:45114.11848422.54786723:20:09114.13328622.6177505085
3680523:36:19114.11296822.54960123:43:12114.08948522.5389185086
3680523:46:14114.09121722.54076823:53:36114.12035422.5443005087

5088 rows × 8 columns

②将od行程分为载客状态下和空载状态下的

data_deliver, data_idle = tbd.taxigps_traj_point(data,oddata,col=['VehicleNum','Time','Lng','Lat','OpenStatus']) data_deliver #载客状态的od路径 VehicleNumTimeLngLatOpenStatusSpeedLONCOLLATCOLIDflag427075427085416622427480416623...6441164405643906440664393
2239600:19:41114.01301622.664818163.085.059.00.01.0
2239600:19:49114.01403022.665483155.085.059.00.01.0
2239600:21:01114.01889822.66250011.086.058.00.01.0
2239600:21:41114.01934822.66230017.086.058.00.01.0
2239600:22:21114.02061522.66336610.086.059.00.01.0
..............................
3680523:53:09114.12035422.54430012.0107.032.05087.01.0
3680523:53:15114.12035422.54430011.0107.032.05087.01.0
3680523:53:21114.12035422.54430010.0107.032.05087.01.0
3680523:53:27114.12035422.54430010.0107.032.05087.01.0
3680523:53:33114.12035422.54430010.0107.032.05087.01.0

209250 rows × 10 columns

data_idle #空载状态的od路径 VehicleNumTimeLngLatOpenStatusSpeedLONCOLLATCOLIDflag416628396136396129401744394630...1709711709541709556439164396
2239600:23:01114.02140022.663918025.086.059.00.00.0
2239600:23:41114.02314822.665100021.087.059.00.00.0
2239600:24:21114.02441422.665367035.087.059.00.00.0
2239600:25:01114.02711522.662100025.088.058.00.00.0
2239600:25:41114.02455122.659834021.087.058.00.00.0
..............................
3680523:45:42114.09121722.54076800.0101.031.05086.00.0
3680523:45:57114.09121722.54076800.0101.031.05086.00.0
3680523:46:12114.09121722.54076800.0101.031.05086.00.0
3680523:53:36114.12035422.54430000.0107.032.05087.00.0
3680523:53:51114.12035422.54430000.0107.032.05087.00.0

332941 rows × 10 columns

可以看出载客状态下数据有20w条,而空载状态下数据有33w条,说明在一天的过程中,总体上处于空载状态的时间是大于载客状态的时间的。
 

三、绘图以及可视化展示

1.GPS轨迹的热力图绘制

# Plot the grids fig = plt.figure(1, (16, 6), dpi=300) ax1 = plt.subplot(111) #ax用于调整大小 # tbd.plot_map(plt, bounds, zoom=10, style=4) datatest.plot(ax=ax1, column='VehicleNum', legend=True) plt.xticks([], fontsize=10) plt.yticks([], fontsize=10) plt.title('Taxi GPS track point count', fontsize=12);

# Plot the grids fig = plt.figure(1, (16, 6), dpi=300) # 确定图形高为6,宽为8;图形清晰度 ax1 = plt.subplot(111) datatest.plot(ax=ax1, column='VehicleNum', legend=True, scheme='quantiles') # plt.legend(fontsize=10) plt.xticks([], fontsize=10) plt.yticks([], fontsize=10) plt.title('Taxi GPS track point count', fontsize=12);

# Plot the grids fig = plt.figure(1, (16, 6), dpi=150) # 确定图形高为6,宽为8;图形清晰度 ax1 = plt.subplot(111) datatest.plot(ax=ax1, column='VehicleNum', legend=True, cmap='OrRd', scheme='quantiles') # plt.legend(fontsize=10) plt.xticks([], fontsize=10) plt.yticks([], fontsize=10) plt.title('Taxi GPS track point count', fontsize=12);

 2.载客状态和空载状态下的od订单图

traj_deliver = tbd.points_to_traj(data_deliver) traj_deliver.plot()

traj_idle = tbd.points_to_traj(data_idle) traj_idle.plot()

 3.依赖keplergl第三方包绘制可交互式的可视化动画

keplergl是由Uber开源的一款地理数据可视化工具,我们可以在Jupyter notebook中使用该工具让我们的数据可视化做到美观。使用前需要先安装,安装教程可参考该篇文章:点击跳转

keplergl官网:点击跳转

①可交互式热力图

# 可视化数据点分布 tbd.visualization_data(data,col = ['Lng','Lat'],accuracy=40,height = 500) #accuracy是栅格大小,数值越大表示一个栅格涵盖地图面积越大

②可交互式OD订单图

# 可视化数据点分布 tbd.visualization_od(oddata,accuracy=2000,height = 500)

 注:同时使用Ctrl和鼠标左键可移动观看视角

③可交互式的视频动图

tbd.visualization_trip(data_deliver) #一天当中的所有载客轨迹

 总结

大家按照上述步骤进行项目,大问题是没有的,之前我遇到的主要问题就是transbigdata的包找了半天,其他的一些如各个包版本之间不适配的问题,可以直接百度解决。本项目的主要难点就是要去理解数据处理的一些函数,这些函数的大概功能我已经在注释中和内容中阐述了。如果有小伙伴想更加深入的了解函数的原理,可以去看transbigdata的源代码,这样可以更加直观的了解这些函数。

补充

如有其他问题,请私信我,谢谢。

上一篇:超详细的实现上传文件功能教程,文件上传实现。

下一篇:C语言课程设计

相关文章

Copyright © 网站出售-网站交易平台 版权信息

网站备案号:黔ICP备2023004141号