文章目录

  • 赛题说明
    • 赛题名称
    • 赛题说明
    • 任务解析
  • 数据清单
  • 算法分析
    • 1.1 巡游车日均空驶率计算
    • 1.2 网约车空驶率部分代码分析
    • 1.3 结果与结果分析
    • 2.1 订单运距与时长计算
    • 2.2 结果与结果分析
    • 3.1 上下客地点可视化实现
    • 3.2 可视化示例
  • 融合发展建议
  • 收获
    • folium库的使用
    • Geohash地点表示
  • 参考文献

赛题说明

赛题名称

A城市巡游车与网约车运营特征对比分析

赛题说明

参赛者需依据赛事方提供的出租车(包括巡游车和网约车)GPS和订单数据

  1. 一是综合应用统计分析方法分别对所提供的巡游车和网约车运营的时间、空间分布特征进行量化计算,包括计算2年的每年工作日取日平均,非工作日取日平均和节假日取日平均,三种类型各自平均的时变分布变化,三种时间类型按网格划分的平均空间分布(网格划分颗粒度选手自选),并分别对比分析所提供的网约车、巡游车,计算2年每年按工作日取日平均,非工作日取日平均和节假日取日平均三种类型的日均空驶率、订单平均运距、订单平均运行时长、上下客点分布密度等时变特性
  2. 二是根据巡游车和网约车的时空运营特征,并尝试对巡游车与网约车的融合发展提出相关建议。在分析过程,参赛者必须用到但不局限于提供的数据,可自行加入自有数据进行参赛,但需说明自带数据来源并保证数据合法合规使用

任务解析

每年工作日取日平均,非工作日取日平均和节假日取日平均,三种情况下出租车&网约车:

  1. 运营时间规律:出车时间和运行时间;

  2. 空间分布规律:城市分布规律,订单分布规律;

  3. 日均空驶率:空驶里程(没有载客)在车辆总运行里程中所占的比例;

  4. 订单平均运距:订单平均距离计算;

  5. 订单平均运行时长:订单平时时长计算;

  6. 上下客点分布密度:上下车位置分布;

  7. 对出租车和网约车的调度、融合发展提出建议,比如如何进行订单调度?识别打不到车的位置

数据清单

  1. 2019年端午节前后10天(5月31日至6月9日)A城市巡游车和网约车的GPS数据和订单数据
  2. 2020年端午节前后10天(6月18日至6月27日)A城市巡游车和网约车的GPS数据和订单数据

算法分析

这里将着重介绍空驶率,订单时长,运距和上下客地点的分析

1.1 巡游车日均空驶率计算

这里以2019年为例,首先载入全部数据的名称:

path_list= ['taxiOrder20190531.csv','taxiOrder20190601.csv','taxiOrder20190602.csv','taxiOrder20190603.csv','taxiOrder20190604.csv','taxiOrder20190605.csv','taxiOrder20190606.csv','taxiOrder20190607.csv','taxiOrder20190608.csv','taxiOrder20190609.csv']

以下是每天运营的巡游车数目(对gps数据进行查看很容易可得出):

nums_car = [6765, 6751, 6714, 6723, 6765, 6761, 6764, 6738, 6737, 6716]

下面对每一天的空驶率进行计算,计算公式如下:

L1表示某天的所有空驶里程,L2表示某天的所有行驶里程,n表示天数。注意上面这个公式所计算的是单个巡游车的空驶率。也就是说我们需要筛选出每一个巡游车的数据,分别计算其空驶率,最后再平均才是当日所有巡游车的空驶率。在这里,单个巡游车的空驶率公式为:

NOPASS_MILE/(PASS_MILE+NOPASS_MILE)

另外还要注意有些车并不存在在订单里,但这些车的确运营了,那就说明这些车当天并没有等到客,也就是说一直都是空驶,那么他们的空驶率为1,因此最后在计算的时候得加上这些车。以下为计算的代码:

day_mean =[]
for i in tqdm(range(len(path_list))):taxiOrder = pd.read_csv(INPUT_PATH + path_list[i])taxiOrder = taxiOrder.rename(columns={'CAR_NO':'CARNO'})taxiOrder.sort_values(by=['CARNO'], inplace=True)taxiOrder.reset_index(inplace=True, drop=True)car_list = taxiOrder['CARNO'].unique()pert_list =[]for car in car_list:single_car = taxiOrder[taxiOrder['CARNO']==car]pert = single_car['NOPASS_MILE'].sum()/(single_car['NOPASS_MILE'].sum()+single_car['PASS_MILE'].sum())pert_list.append(pert)pert_list.extend([1]*(nums_car[i]-len(pert_list)))print("订单空驶率",np.mean(pert_list))day_mean.append(pert_list)

计算完每天的空驶率,也就可以得到相应的工作日,周末和端午节日均空驶率。

1.2 网约车空驶率部分代码分析

这里我们以2020年为例:

其实网约车和巡游车的空驶率计算方法相似,但是在网约车的数据里有很多的脏数据,需要进行处理。比如在网约车的订单运距DRIVE_MILE一列出现了字符类型,在将这些行的数据筛选出来后发现,这些数据是完全的脏数据,可以直接删除。

另外在WAIT_MILE一列中有很多缺失数据。通过数据分析和生活实际我们可以判断其可以直接以0进行代替。因为对于网约车来说,很多是载客过程中已经接到订单,所有空驶距离没法上报,设为空值。但很明显这里空驶距离为0。

具体空驶率计算就是WAIT_MILE/(DRIVE_MILE+WAIT_MILE),其他就与巡游车一致。以下列出网约车数据处理部分代码:

day_mean =[]
for i in range(len(path_list)):wycOrder = pd.read_csv(INPUT_PATH + path_list[i],usecols=[2,11,13])wycOrder = wycOrder.rename(columns={'CAR_NO':'CARNO'})wycOrder = wycOrder[wycOrder['DRIVE_MILE'].apply(lambda x: '-' not in str(x) and '|' not in str(x) and '路' not in str(x))]wycOrder['DRIVE_MILE'] = wycOrder['DRIVE_MILE'].astype(float)wycOrder['WAIT_MILE'] = wycOrder['WAIT_MILE'].astype(float)wycOrder = wycOrder.fillna(0)wycOrder.sort_values(by=['CARNO'], inplace=True)wycOrder.reset_index(inplace=True, drop=True)car_list = wycOrder['CARNO'].unique()pert_list =[]for car in tqdm(car_list):single_car = wycOrder[wycOrder['CARNO']==car]pert = (single_car['WAIT_MILE'].sum()+0.0001)/(single_car['WAIT_MILE'].sum()+single_car['DRIVE_MILE'].sum()+0.0001)pert_list.append(pert)pert_list.extend([1]*(nums_car[i]-len(pert_list)))print("订单空驶率",np.mean(pert_list))day_mean.append(pert_list)

1.3 结果与结果分析


从上图可以发现,网约车的空驶率要明显低于巡游车的空驶率。根据本人推测以及结合实际情况的分析,巡游车与网约车空驶率这么大的差距源于两者的营业方式。网约车一般都是接收的网络订单,很多情况下并不会在空车情况下到处寻找是否有在路边扬招的乘客。而巡游车则不同,巡游车很少有网络订单,在空车情况下往往会去路上来回空驶,寻找扬招的乘客。当然由于其统一的外观也比较容易接到扬招的乘客。因此,正是上面的差别导致了网约车在空车情况下不会过多的进行空驶,只需要等待网络订单即可,而巡游车在空车情况下往往会进行大量的空驶来寻找乘客。

在端午假期期间的空驶率要高于其他两个时间段的空驶率,可能由于端午假期期间人流量相对往常要少很多,再加上假期期间不限号,很多人选择私家车出行,也导致出租车网约车接不到客从而空驶的情况。

2020年的空驶率要微高于2019年的,可能是由于今年疫情影响,尤其是对于巡游车,客户不会聚集等车而是分散,所以使得空驶率提高。

2.1 订单运距与时长计算

通过分析发现,巡游车的数据较为干净。所以这里计算订单的平均运距直接将订单数据中的PASS_MILE那一列数据求平均。同样的平均时长直接是下车时间减去上车时间然后求平均。以下是相关代码:

# 巡游车计算
def cal_taxi(df):df['GETON_DATE'] = pd.to_datetime(df['GETON_DATE'])df['GETOFF_DATE'] = pd.to_datetime(df['GETOFF_DATE'])print(df['PASS_MILE'].mean(),'|',((df['GETOFF_DATE'] - df['GETON_DATE']).dt.seconds / 60.0).mean())

对于网约车平均运距的计算也相似,但是需要对数据进行预处理,在上面计算空驶率的时候我们已经了解到,在网约车的DRIVE_MILE一列有一些脏数据,那么和上面同样的处理方法,直接删除然后对这一列求平均即可得到平均运距

对于网约车订单平均时长的计算也是一样,但是在分析数据时我们发现有很多条数据的上车时间DEP_TIME竟然小于DEST_TIME,这明显是错误的数据。但是查看他们的行驶时间会发现,他们的行驶时间都很大。这里根据实际情况我们猜测该订单其实跨越了两天,因此这里我们直接使用行驶时间作参考。最后得到的订单时长中,我们又将超出一天的订单时间改为一天时间,记为1440分钟。以下为网约车订单平均运距和平均时长的代码:

def cal_wyc(df):df = df[['DEST_TIME', 'DEP_TIME', 'DRIVE_MILE']].dropna()if df['DEST_TIME'].dtype != np.int64:df = df[df['DEST_TIME'].apply(len) == 14]df = df[df['DEST_TIME'].apply(lambda x: x.isdigit())]df['DEP_TIME'] = pd.to_datetime(df['DEP_TIME'], format='%Y%m%d%H%M%S')df['DEST_TIME'] = pd.to_datetime(df['DEST_TIME'], format='%Y%m%d%H%M%S')df = df[df['DRIVE_MILE'].apply(lambda x: '-' not in str(x) and '|' not in str(x) and '路' not in str(x))]df['DRIVE_MILE'] = df['DRIVE_MILE'].astype(float)driveMile_mean = df['DRIVE_MILE'].dropna().mean()df['dev'] = (df['DEST_TIME'] - df['DEP_TIME']).dt.seconds / 60.0df.loc[df['DEST_TIME']<df['DEP_TIME'],'dev'] = 0df.loc[df['dev']>1440,'dev']=1440print(driveMile_mean,'|',df['dev'].mean())

2.2 结果与结果分析

网约车的平均运距要显著高于巡游车,这是很好理解的,网约车在用户下单后去接用户那段距离也是算在订单运距里面的。而且巡游车一般不跑远路,这也是一个原因。

网约车数据方面,可以直观看出端午假期期间的运距高于其他两个假期,这可能是由于端午假期很多人出门旅游或者回乡探亲的原因。

另外2020年巡游车的订单平均运距普遍低于2019年,而2020网约车的订单平均运距高于2019年

从上面两图可以发现网约车的订单时长明显高于巡游车。而且两车在工作日的订单时长都要高于其他的两个时段

3.1 上下客地点可视化实现

这里对于上下客分布地点的分析我们采用了两种可视化分析方案,一是对热门下车地区进行可视化,而是对上下客地点分布密度进行可视化。两者我们都使用了python中的folium库。

以2020年的巡游车上车点为例,首先读取数据,这里因为我们仅仅需要上下客地点的经纬度,所以只读取相关的列即可:

path_list= [  'taxiOrder20200618.csv','taxiOrder20200619.csv','taxiOrder20200620.csv','taxiOrder20200621.csv','taxiOrder20200622.csv','taxiOrder20200623.csv','taxiOrder20200624.csv','taxiOrder20200625.csv','taxiOrder20200626.csv','taxiOrder20200627.csv']taxiOrder2020 = pd.concat([pd.read_csv(INPUT_PATH + x,usecols = [0,2,3,5,6]) for x in path_list])

接着我们需要对数据进行筛选,删除经纬度异常的数据,然后对于经纬度我们还选取4为有效小数,是为后面可视化分布密度服务的。其实这里也可以用geohash,效果相似。

taxiOrder2020[['GETON_LONGITUDE','GETON_LATITUDE','GETOFF_LONGITUDE','GETOFF_LATITUDE']] = taxiOrder2020[['GETON_LONGITUDE','GETON_LATITUDE','GETOFF_LONGITUDE','GETOFF_LATITUDE']].round(4)taxiOrder2020 = taxiOrder2020.loc[(taxiOrder2020['GETON_LONGITUDE']>110)&(taxiOrder2020['GETON_LONGITUDE']<128)&(taxiOrder2020['GETON_LATITUDE']>15)&(taxiOrder2020['GETON_LATITUDE']<35),:]

接下来对相同的上车地点进行聚合,以条目为统计值,这样我们可以获得相近区域(因为取了四位小数)的上车点的订单数,将其排序即可得到热门的上车点。然后选取前100个上车地点并标记到地图上即可实现对热门下车点的可视化。

taxi_grouped_geton = taxiOrder2020[['CAR_NO','GETON_LONGITUDE','GETON_LATITUDE']].groupby(by = ['GETON_LONGITUDE','GETON_LATITUDE']).count().sort_values(by ='CAR_NO',ascending = False)taxi_grouped_lonla = pd.DataFrame({'GETON_LATITUDE':[item[1] for item in taxi_grouped_geton.index[:100]],'GETON_LONGITUDE':[item[0] for item in taxi_grouped_geton.index[:100]]})map_hooray = folium.Map(location=[24.482426, 118.1], zoom_start=12)tooltip = 'Click me!'i = 1for tup in taxi_grouped_lonla[['GETON_LATITUDE','GETON_LONGITUDE']].values:folium.Marker(tup, popup="rank:"+str(i), tooltip=tooltip).add_to(map_hooray)i+=1map_hooray

接着从上面聚合的数据taxi_grouped_geton,我们可以提取出密度特征,我们,我们根据相同地点出现的条数,一次又一次的往地图上画点,那么出现多的地点周围颜色就深,反之出现少的地点就浅,这样就可以实现下车地点分布密度的可视化。

这里并不建议根据数据中所有的地点信息来在地图上实现密度可视化,因为数据量很大,这样做就会使得地图上全被画满了,这样的可视化结果几乎没有区分度,看不出各个地区的密度对比。

GETON_LONGITUDE_list =[]GETON_LATITUDE_list = []for i in range(3000):times = int(taxi_grouped_geton['CAR_NO'].values[i]/100)GETON_LONGITUDE_list.extend([taxi_grouped_geton.index[i][0]]*times)GETON_LATITUDE_list.extend([taxi_grouped_geton.index[i][1]]*times)df_heat_map = pd.DataFrame({'GETON_LATITUDE': GETON_LATITUDE_list,'GETON_LONGITUDE':GETON_LONGITUDE_list})map_hooray = folium.Map(location=[24.482426, 118.1], zoom_start=12)HeatMap(df_heat_map[['GETON_LATITUDE','GETON_LONGITUDE']].values).add_to(map_hooray)map_hooray

3.2 可视化示例

融合发展建议

  1. 由于网约车数据中包含很多脏数据,我在数据分析过程中碰到了不少麻烦,所以我建议加大对网约车的信息跟踪与核实

  2. 从上面那些量化指标我们可以得出这样的结论,在可预见的未来,由于打车软件的越来越普及以及网约车方便快速,出租车也就是巡游车行业会受到巨大冲击,因此有关部门可以考虑对其进行转型。具体方案如下两种:

    • 如果条件允许的话,在每一片区域为巡游车设置固定的停靠点,当巡游车结束一个订单后应立即驶向附近的停靠点,而不是在路上空驶,增加交通压力。而乘客需要乘车时,没必要在路边扬招,而是去附近的固定停车点乘车即可。

    • 上面这个方案有一个缺点就是乘客失去了便捷,因此这里可以参考网约车的优势,将巡游车的下单方式也采取网上进行。也就是巡游车还是停在固定的停靠点,当乘客在网络上下单后,离他最近的一个停靠点会派一辆巡游车来接这位乘客。当乘客到达目的地后,同样的该巡游车需要驶往最近的停靠点。

收获

folium库的使用

建立一个基础地图:


import folium#location 表示显示的中心地点,zoom_start为初始显示的缩放比例
m = folium.Map(location=[45.5236, -122.6750],zoom_start=12)
m

保存该地图:

m.save('index.html')

画标记点以及热度图见算法分析部分的3.1

Geohash地点表示

GeoHash将二维的经纬度转换成字符串,比如下图展示了北京9个区域的 GeoHash字符串,每一个字符串代表了某一矩形区域。 字符串越长,表示的范围越精确。

使用Geohash的优点在于

  1. 既能表明用户位于某个地区附近,又不至于暴露用户的精确坐标,有助于隐私保护。

  2. 也有助于热力图展示,地址聚类等

python里的使用方法:

import geohash
#将经纬度转换为geohash编码,precision的值为输出编码的长度
taxiorder2019['geohash'] = taxiorder2019.apply(lambda x: geohash.encode(x['GETON_LATITUDE'], x['GETON_LONGITUDE'], precision=8), axis=1)
taxiorder2019['geohash'].value_counts().head()out:s0000000    6335ws7unv0q     808wsk584c9     746ws7grb9s     604ws7unv0r     603

解码一个GeoHash编码示例:

>>> print 'Coordinate for Geohash ezs42:', Geohash.decode('ezs42')
Coordinate for Geohash ezs42: ('42.6', '-5.6')

Geohash模块还提供精确的解码,并带有误差余量结果。 encode_exactly函数返回四个浮点值的元组。 纬度,经度,纬度误差幅度,经度误差幅度:

>>> print 'Exact coordinate for Geohash ezs42:\n', Geohash.decode_exactly('ezs42')
Exact coordinate for Geohash ezs42:
(42.60498046875, -5.60302734375, 0.02197265625, 0.02197265625)

其实这里的误差幅度也就是表示Geohash编码所表示的那个正方形区域。

参考文献

  1. Coggle数据学习。URL: https://coggle.club/learn/dcic2020/
  2. GeoHash核心原理解析。 URL: https://www.cnblogs.com/LBSer/p/3310455.html
  3. GeoHash文档。 URL: https://libraries.io/pypi/Geohash

DCIC-赛题二赛后总结相关推荐

  1. 蓝桥杯单片机省赛第十一届赛题二

    文章目录 前言 一.题目​​ 二.代码部分 1.IIC.C 2.IIC.H 3.onewire.h 4.onewire.h 5. main.c 总结 前言 蓝桥杯单片机--第十一届省赛赛题二解析 今年 ...

  2. 全国职业院校技能大赛网络建设与运维赛项赛题(二)

    全国职业院校技能大赛 网络建设与运维 赛题 (二)

  3. 全国职业院校技能大赛 网络建设与运维 赛题(二)【201题起】

    目录 模块二:网络建设与调试 一.工程统筹 二.交换配置 三.路由调试 四.无线部署 五.安全维护 模块三:服务搭建与运维 一.X86架构计算机操作系统安装与管理 二.ARM架构计算机操作系统安装与管 ...

  4. 年度最Hot,三大热点赛题,首届「马栏山」杯国际音视频算法大赛正式开赛

    不久之前,一段使用人工智能修复老北京影像的视频火爆全网,引起了极大的关注.这段修复视频,让我们无须穿越,就能体验一把 100 年前的老北京生活. 在这段效果惊艳的修复视频背后,用到了多项前沿研究,如基 ...

  5. CCF BDCI大赛急速报名,OneFlow四大训练赛题等你来战

    CCF大数据与计算智能大赛(CCF Big Data & Computing Intelligence Contest,简称CCF BDCI)由国家自然科学基金委员会指导,是大数据与人工智能领 ...

  6. 国内首本数据竞赛图书《阿里云天池大赛赛题解析——机器学习篇》今日开启预售!

    天池平台已经举办了超过 200 场来自真实业务场景的竞赛,每场赛事沉淀的课题和数据集,将在天池保留和开放.天池平台已成为在校学生踏入职场前的虚拟实践基地,也成为聚集40万数据人才,孵化2000余家数据 ...

  7. 【赠书】阿里云天池大赛赛题解析,深度学习篇!

    ‍‍ 阿里云天池作为国内知名的竞赛平台和AI社区,自诞生以来就一直秉持着让更多人公平获得大数据的理念.也正因此,天池每场经典赛事沉淀的课题和数据集都会永久保留和开放.截至目前,天池平台已举办了超过20 ...

  8. AI开发者看过来:搞定这四道赛题 赢取30万大奖

    JDD-2017京东金融全球数据探索者大赛终于在11月6日启动报名了!这是一场面向全球AI与数据人才的人工智能大赛,优胜团队不仅可以获得30万元高额奖金,同时有机会获得京东金融或合作机构的优先投资!大 ...

  9. 2023年全国职业院校技能大赛 高等职业教育组 (信息安全管理与评估样题二)

    全国职业院校技能大赛 高等职业教育组 信息安全管理与评估 赛题二 模块一 网络平台搭建与设备安全防护   一. 赛项时间 共计180分钟. 二. 赛项信息 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 ...

最新文章

  1. 从SAP Hybris下单,同步到S/4HANA,触发生产流程
  2. 全国高等学校计算机等级考试(江西考区)一级笔试试卷a,全国高等学校计算机等级考试(江西考区)一级笔试试卷A...
  3. python中的random模块_Python中的random模块
  4. 中国要做物联网技术的强国,而非大国
  5. [Asp.Net Core]Session的使用
  6. 性能测试:竞品APP性能对比测试
  7. 关于python语句与列表,元组,字典等集合的题
  8. STM32F107VCT6开发板 CAN总线通信实验----发送和接收
  9. hdu6287(分解质因数+二分)
  10. explain是mysql的关键字吗_mysql 中的explain关键字
  11. Django批量修改 get_field_display foreignkey
  12. WAIC直击:星环科技以大数据AI技术构建新型数字底座
  13. 装修新房该不该换电线
  14. zone2021 E-Sneaking
  15. 设置硬件时间和系统时间
  16. android清理安全app测试经验总结
  17. 关于AsyncHttpClient的cz.msebera.android.httpclient.Header
  18. android zigbee环境监测,基于ZigBee技术的室内定位与环境监测系统
  19. linux通过无线网卡上网,在Ubuntu中使用PHS无线网卡上网
  20. 数据库系统的内部体系(三级模式二级映像)

热门文章

  1. 一篇文章搞懂互联网商业模式,以及一些鲜为人知的玩法
  2. 【图像去噪】基于matlab小波变换(硬阙值+软阙值+折中阙值+最佳阙值)图像去噪【含Matlab源码 2596期】
  3. eclispe 4.10无法创建tomcat,显示红色方块以及“Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4, and Java E...
  4. FZU 1962 新击鼓传花游戏
  5. HTTP协议的无状态和无连接
  6. inmp构架搭建Wordpress博客
  7. 解决正点原子Linux开发板配置静态IP重启后失效的问题
  8. 无限试用30天phpstorm
  9. 量化lstm为onnx遇到end值越界的解决方法
  10. python之__len__()