早高峰共享单车潮汐点的群智优化Baseline

参考自:coogle数据科学 https://coggle.club/learn/dcic2021/

一、赛题说明

2021数字中国创新大赛大数据赛道-城市管理大数据专题

二、数据读取与理解

共享单车轨迹数据

共享单车轨迹数据为共享单车在使用时候产生的位置定位数据,具体包含单车在不同时间段(默认是15秒记录一次)下的经纬度信息。

  • 读取数据:读取单车轨迹数据:
import os, codecs
import pandas as pd
import numpy as np

PATH = '../dataset/'
# 共享单车轨迹数据
bike_track = pd.concat([
    pd.read_csv(PATH + 'gxdc_gj20201221.csv'),
    pd.read_csv(PATH + 'gxdc_gj20201222.csv'),
    pd.read_csv(PATH + 'gxdc_gj20201223.csv'),
    pd.read_csv(PATH + 'gxdc_gj20201224.csv'),
    pd.read_csv(PATH + 'gxdc_gj20201225.csv')

])

# 按照单车ID和时间进行排序
bike_track = bike_track.sort_values(['BICYCLE_ID', 'LOCATING_TIME'])
  • 路线可视化
import folium
m = folium.Map(location=[24.482426, 118.157606], zoom_start=12)
my_PolyLine=folium.PolyLine(locations=bike_track[bike_track['BICYCLE_ID'] == '000152773681a23a7f2d9af8e8902703'][['LATITUDE', 'LONGITUDE']].values,weight=5)
m.add_children(my_PolyLine)

在这里插入图片描述

共享单车停车点位(电子围栏)数据

共享单车停车点位(电子围栏)数据为规范共享单车停车秩序,统一划定的共享单车停放区域。

  • 读取数据
def bike_fence_format(s):
    s = s.replace('[', '').replace(']', '').split(',')
    s = np.array(s).astype(float).reshape(5, -1)
    return s

# 共享单车停车点位(电子围栏)数据
bike_fence = pd.read_csv(PATH + 'gxdc_tcd.csv')
bike_fence['FENCE_LOC'] = bike_fence['FENCE_LOC'].apply(bike_fence_format)
  • 围栏可视化
import folium
m = folium.Map(location=[24.482426, 118.157606], zoom_start=12)

for data in bike_fence['FENCE_LOC'].values[:100]:
    folium.Marker(
        data[0, ::-1]
    ).add_to(m)
m

在这里插入图片描述

共享单车订单数据

共享单车订单数据为共享单车使用时开锁和关锁信息的数据。

  • 读取数据
# 共享单车订单数据
bike_order = pd.read_csv(PATH + 'gxdc_dd.csv')
bike_order = bike_order.sort_values(['BICYCLE_ID', 'UPDATE_TIME'])
  • 单车位置可视化
import folium
m = folium.Map(location=[24.482426, 118.157606], zoom_start=12)
my_PolyLine=folium.PolyLine(locations=bike_order[bike_order['BICYCLE_ID'] == '0000ff105fd5f9099b866bccd157dc50'][['LATITUDE', 'LONGITUDE']].values,weight=5)
m.add_children(my_PolyLine)

在这里插入图片描述

轨道交通数据

  • 数据读取
# 轨道站点进站客流数据
rail_inflow = pd.read_excel(PATH + 'gdzdtjsj_jzkl.csv')
rail_inflow = rail_inflow.drop(0)

# 轨道站点出站客流数据
rail_outflow = pd.read_excel(PATH + 'gdzdtjsj_czkl.csv')
rail_outflow = rail_outflow.drop(0)

# 轨道站点闸机设备编码数据
rail_device = pd.read_excel(PATH + 'gdzdkltj_zjbh.csv')
rail_device.columns = [
    'LINE_NO', 'STATION_NO', 'STATION_NAME',
    'A_IN_MANCHINE', 'A_OUT_MANCHINE', 
    'B_IN_MANCHINE', 'B_OUT_MANCHINE'
]
rail_device = rail_device.drop(0)

三、共享单车潮汐点分析

经纬度匹配

在本赛题中如果想要完成具体潮汐计算,则需要将订单或轨迹与具体的停车点进行匹配,需要计算在不同时间下每个停车点:

  • 停了多少车(订单终点为停车点);
  • 骑走多少车(订单起点为停车点);

因此我们需要根据订单定位到具体的停车点:
在这里插入图片描述

停车点处理

首先我们对停车点进行处理,需要计算得出每个停车点的面积和中心经纬度:

# 得出停车点 LATITUDE 范围
bike_fence['MIN_LATITUDE'] = bike_fence['FENCE_LOC'].apply(lambda x: np.min(x[:, 1]))
bike_fence['MAX_LATITUDE'] = bike_fence['FENCE_LOC'].apply(lambda x: np.max(x[:, 1]))

# 得到停车点 LONGITUDE 范围
bike_fence['MIN_LONGITUDE'] = bike_fence['FENCE_LOC'].apply(lambda x: np.min(x[:, 0]))
bike_fence['MAX_LONGITUDE'] = bike_fence['FENCE_LOC'].apply(lambda x: np.max(x[:, 0]))

from geopy.distance import geodesic
# 根据停车点 范围 计算具体的面积
bike_fence['FENCE_AREA'] = bike_fence.apply(lambda x: geodesic(
    (x['MIN_LATITUDE'], x['MIN_LONGITUDE']), (x['MAX_LATITUDE'], x['MAX_LONGITUDE'])
).meters, axis=1)

# 根据停车点 计算中心经纬度
bike_fence['FENCE_CENTER'] = bike_fence['FENCE_LOC'].apply(
    lambda x: np.mean(x[:-1, ::-1], 0)
)

中心经纬度可以用来具体的距离匹配,当然如果用四个点的坐标会更加准确,但计算时间更大。

Geohash经纬度匹配

在赛题中计算单车与停车点的关系主要的就在经纬度计算,如何将单车维度与停车点进行匹配?这个问题会影响具体的匹配精度,同时也会影响匹配的速度。在此我们使用geohash库来对经纬度进行编码,这样可以增加统计的速度,也可以动态调整经纬匹配的范围。

如果想深入了解geohash,可以参考以下链接:

通过geohash可以将一个经纬度编码为一个字符串,需要注意的是precision控制了编码精度,数值越大覆盖范围越小,数值越小覆盖范围越大。

需要注意:这里的precision与具体的定位点范围强相关,需要根据具体的赛题要求完成设置。

import geohash
bike_order['geohash'] = bike_order.apply(
    lambda x: geohash.encode(x['LATITUDE'], x['LONGITUDE'], precision=6), 
axis=1)

bike_fence['geohash'] = bike_fence['FENCE_CENTER'].apply(
    lambda x: geohash.encode(x[0], x[1], precision=6)
)

使用ws7gx9对单车订单数据进行索引,可以得到具体订单数据:

# bike_order[bike_order['geohash'] == 'ws7gx9']

在这里插入图片描述

区域流量与潮汐统计

在完成具体的经纬度匹配后,接下来就需要完成具体的区域流量统计,即统计某一范围内的不同时间的流量(入流量和出流量)。

首先对订单数据进行时间提取:

bike_order['UPDATE_TIME'] = pd.to_datetime(bike_order['UPDATE_TIME'])
bike_order['DAY'] = bike_order['UPDATE_TIME'].dt.day.astype(object)
bike_order['DAY'] = bike_order['DAY'].apply(str)

bike_order['HOUR'] = bike_order['UPDATE_TIME'].dt.hour.astype(object)
bike_order['HOUR'] = bike_order['HOUR'].apply(str)
bike_order['HOUR'] = bike_order['HOUR'].str.pad(width=2,side='left',fillchar='0')

# 日期和时间进行拼接
bike_order['DAY_HOUR'] = bike_order['DAY'] + bike_order['HOUR']

使用透视表统计每个区域在不同时间的入流量和出流量:

bike_inflow = pd.pivot_table(bike_order[bike_order['LOCK_STATUS'] == 1], 
                   values='LOCK_STATUS', index=['geohash'],
                    columns=['DAY_HOUR'], aggfunc='count', fill_value=0
)

bike_outflow = pd.pivot_table(bike_order[bike_order['LOCK_STATUS'] == 0], 
                   values='LOCK_STATUS', index=['geohash'],
                    columns=['DAY_HOUR'], aggfunc='count', fill_value=0
)

通过以上代码就可以统计完成区域流量,接下来可以做简单的绘图:

bike_inflow.loc['wsk593'].plot()
bike_outflow.loc['wsk593'].plot()
plt.xticks(list(range(bike_inflow.shape[1])), bike_inflow.columns, rotation=40)
plt.legend(['入流量', '出流量'])

在这里插入图片描述

bike_inflow.loc['wsk52r'].plot()
bike_outflow.loc['wsk52r'].plot()
plt.xticks(list(range(bike_inflow.shape[1])), bike_inflow.columns, rotation=40)
plt.legend(['入流量', '出流量'], prop = prop)

在这里插入图片描述

方法1:Geohash匹配计算潮汐

由于赛题需要统计工作日早高峰期间的潮汐现象,所以我们可以按照天进行单车流量统计:

bike_inflow = pd.pivot_table(bike_order[bike_order['LOCK_STATUS'] == 1], 
                   values='LOCK_STATUS', index=['geohash'],
                    columns=['DAY'], aggfunc='count', fill_value=0
)

bike_outflow = pd.pivot_table(bike_order[bike_order['LOCK_STATUS'] == 0], 
                   values='LOCK_STATUS', index=['geohash'],
                    columns=['DAY'], aggfunc='count', fill_value=0
)

根据入流量和出流量,可以计算得到每个位置的留存流量:

bike_remain = (bike_inflow - bike_outflow).fillna(0)

# 存在骑走的车数量 大于 进来的车数量
bike_remain[bike_remain < 0] = 0  

# 按照天求平均
bike_remain = bike_remain.sum(1)

这里假设我们需要统计街道维度的潮汐情况,我们可以先把街道信息提取,然后计算密度。这里我们需要计算每个街道不同停车点的留存车辆,所以不能重复统计。

# 总共有993条街
bike_fence['STREET'] = bike_fence['FENCE_ID'].apply(lambda x: x.split('_')[0])

# 留存车辆 / 街道停车位总面积,计算得到密度
bike_density = bike_fence.groupby(['STREET'])['geohash'].unique().apply(
    lambda hs: np.sum([bike_remain[x] for x in hs])
) / bike_fence.groupby(['STREET'])['FENCE_AREA'].sum()

# 按照密度倒序
bike_density = bike_density.sort_values(ascending=False).reset_index()

就可以得到潮汐情况最严重的道路:
在这里插入图片描述

方法2:距离匹配计算潮汐

如果使用Geohash来统计会存在一个问题,统计的方法会不准确,导致只能精确到街道信息。本节将使用经纬度距离匹配的方法来进行尝试,具体的思路为计算订单最近的停车点,进而计算具体的潮汐情况。

对于经纬度距离计算,可以直接使用sklearn中的NearestNeighbors,通过设置haversine距离可以很方便的完成最近停车点的计算。

from sklearn.neighbors import NearestNeighbors

# https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.DistanceMetric.html
knn = NearestNeighbors(metric = "haversine", n_jobs=-1, algorithm='brute')
knn.fit(np.stack(bike_fence['FENCE_CENTER'].values))

计算订单中对应的停车点位置:

# 需要11s左右
dist, index = knn.kneighbors(bike_order[['LATITUDE','LONGITUDE']].values[:20000], n_neighbors=1)

但是如果直接使用NearestNeighbors计算速度会非常慢,如果是全量定量订单数据可能需要较长时间。因此可以用hnsw做近似搜索,速度较快但精度差一点。

import hnswlib
import numpy as np

p = hnswlib.Index(space='l2', dim=2)
p.init_index(max_elements=300000, ef_construction=1000, M=32)
p.set_ef(1024)
p.set_num_threads(14)

p.add_items(np.stack(bike_fence['FENCE_CENTER'].values))

计算所有订单的停车位置:

index, dist = p.knn_query(bike_order[['LATITUDE','LONGITUDE']].values[:], k=1)

然后计算所有停车点的潮汐流量:

bike_order['fence'] = bike_fence.iloc[index.flatten()]['FENCE_ID'].values

bike_inflow = pd.pivot_table(bike_order[bike_order['LOCK_STATUS'] == 1], 
                   values='LOCK_STATUS', index=['fence'],
                    columns=['DAY'], aggfunc='count', fill_value=0
)

bike_outflow = pd.pivot_table(bike_order[bike_order['LOCK_STATUS'] == 0], 
                   values='LOCK_STATUS', index=['fence'],
                    columns=['DAY'], aggfunc='count', fill_value=0
)

bike_remain = (bike_inflow - bike_outflow).fillna(0)
bike_remain[bike_remain < 0] = 0  
bike_remain = bike_remain.sum(1)

计算停车点的密度:

bike_density = bike_remain / bike_fence.set_index('FENCE_ID')['FENCE_AREA']
bike_density = bike_density.sort_values(ascending=False).reset_index()
bike_density = bike_density.fillna(0)

在这里插入图片描述

四、共享单车潮汐点优化

根据上面的街道潮汐统计,我们可以统计得出每个街道的具体潮汐情况,并进而可以按照密度计算得到潮汐情况最为严重的区域。为了对厦门市潮汐情况与区域关系进行可视化,来对具体的潮汐情况进行直观的感受。

首先我们按照之前的代码完成具体数据读取,并对单车订单数据的时间进行提取:

bike_order['UPDATE_TIME'] = pd.to_datetime(bike_order['UPDATE_TIME'])
bike_order['DAY'] = bike_order['UPDATE_TIME'].dt.day.astype(object)
bike_order['DAY'] = bike_order['DAY'].apply(str)

bike_order['HOUR'] = bike_order['UPDATE_TIME'].dt.hour.astype(object)
bike_order['HOUR'] = bike_order['HOUR'].apply(str)
bike_order['HOUR'] = bike_order['HOUR'].str.pad(width=2,side='left',fillchar='0')

bike_order['DAY_HOUR'] = bike_order['DAY'] + bike_order['HOUR']

为了方便统计这里,我们只使用一个时间的订单数据进行绘制:

import folium
from folium import plugins
from folium.plugins import HeatMap

map_hooray = folium.Map(location=[24.482426, 118.157606], zoom_start=14)
HeatMap(bike_order.loc[(bike_order['DAY_HOUR'] == '2106') & (bike_order['LOCK_STATUS'] == 1), 
                   ['LATITUDE', 'LONGITUDE']]).add_to(map_hooray)

for data in bike_fence['FENCE_LOC'].values[::10]:
    folium.Marker(
        data[0, ::-1]
    ).add_to(map_hooray)

map_hooray

在这里插入图片描述如上图,我们可以看到颜色表示为具体停车位置的热度,具体点为订车点的位置。

  • 并不是所有的车都听到了停车点,有一些车听到了距离停车点较远的距离;
  • 有一些停车点有潮汐现象,有的不存在潮汐现象;

其他停车点推荐

根据之前的街道潮汐统计,我们可以得到每个停车点具体的潮汐情况。如果此停车点停满了,进一步我们也可以推荐其他停车点。

我们使用下面的代码完成具体的停车点潮汐统计:

import geohash
bike_order['geohash'] = bike_order.apply(lambda x: 
                        geohash.encode(x['LATITUDE'], x['LONGITUDE'], precision=9), axis=1)

from geopy.distance import geodesic

bike_fence['MIN_LATITUDE'] = bike_fence['FENCE_LOC'].apply(lambda x: np.min(x[:, 1]))
bike_fence['MAX_LATITUDE'] = bike_fence['FENCE_LOC'].apply(lambda x: np.max(x[:, 1]))

bike_fence['MIN_LONGITUDE'] = bike_fence['FENCE_LOC'].apply(lambda x: np.min(x[:, 0]))
bike_fence['MAX_LONGITUDE'] = bike_fence['FENCE_LOC'].apply(lambda x: np.max(x[:, 0]))

bike_fence['FENCE_AREA'] = bike_fence.apply(lambda x: geodesic(
    (x['MIN_LATITUDE'], x['MIN_LONGITUDE']), (x['MAX_LATITUDE'], x['MAX_LONGITUDE'])
).meters, axis=1)

bike_fence['FENCE_CENTER'] = bike_fence['FENCE_LOC'].apply(
    lambda x: np.mean(x[:-1, ::-1], 0)
)

import geohash
bike_order['geohash'] = bike_order.apply(
    lambda x: geohash.encode(x['LATITUDE'], x['LONGITUDE'], precision=7), 
axis=1)

bike_fence['geohash'] = bike_fence['FENCE_CENTER'].apply(
    lambda x: geohash.encode(x[0], x[1], precision=7)
)

bike_inflow = pd.pivot_table(bike_order[bike_order['LOCK_STATUS'] == 1], 
                   values='LOCK_STATUS', index=['geohash'],
                    columns=['DAY'], aggfunc='count', fill_value=0
)

bike_outflow = pd.pivot_table(bike_order[bike_order['LOCK_STATUS'] == 0], 
                   values='LOCK_STATUS', index=['geohash'],
                    columns=['DAY'], aggfunc='count', fill_value=0
)

bike_remain = (bike_inflow - bike_outflow).fillna(0)
bike_remain[bike_remain < 0] = 0  
bike_remain = bike_remain.sum(1)
bike_fence['DENSITY'] = bike_fence['geohash'].map(bike_remain).fillna(0)

如果乘客到了一个潮汐停车点A,如何对乘客进行引导呢?

  • 推荐的停车点B应该和A距离不远;
  • 推荐的停车点B应该没有潮汐情况;
  • 也需要考虑到跨街道和横穿马路的情况;

首先为了完成停车点距离计算,还是先定义好KNN:

from sklearn.neighbors import NearestNeighbors

knn = NearestNeighbors(metric = "haversine", n_jobs=-1, algorithm='brute')
knn.fit(np.stack(bike_fence['FENCE_CENTER'].values))

然后是具体的计算逻辑进行编码:

def fence_recommend1(fence_id):
    fence_center = bike_fence.loc[bike_fence['FENCE_ID']==fence_id, 'FENCE_CENTER'].values[0]
    # 具体街道方向
    fence_dir = fence_id.split('_')[1]
    # 根据距离计算最近的20个待选位置
    dist, index = knn.kneighbors([fence_center], n_neighbors=20)

    # 对每个待选位置进行筛选
    for idx in index[0]:
        # 剔除已经有很多车的
        if bike_fence.iloc[idx]['DENSITY'] > 10:
            continue
        # 剔除需要过街的
        if fence_dir not in bike_fence.iloc[idx]['FENCE_ID']:
            continue
        return bike_fence.iloc[idx]['FENCE_ID']

    return None

停车引导计划

此外还需要考虑到单车没有起到停车点的情况,即推荐根据经纬度推荐最近非潮汐停车点:

def fence_recommend2(la, lo):
    dist, index = knn.kneighbors([[la, lo]], n_neighbors=20)
    for idx in index[0][1:]:
        if bike_fence.iloc[idx]['DENSITY'] > 10:
            continue
        return bike_fence.iloc[idx]['FENCE_ID']

    return None

综上所述我们可以将潮汐引导计划描述如下,分为两种情况:
综上所述我们可以将潮汐引导计划描述如下,分为两种情况:

五、共享单车调度方案

单车利用率

共享单车作为城市交通中重要的一环,可以方便市民便捷出行。但单车具体的位置随着群体波动,并且容易出现单车潮汐和分布不均衡的情况,最终导致单车利用率较低。
在这里插入图片描述
首先我们可以统计不同品牌单车的利用率:

# 共享单车轨迹数据
bike_track = pd.concat([
    pd.read_csv(PATH + 'gxdc_gj20201221.csv'),
    pd.read_csv(PATH + 'gxdc_gj20201222.csv'),
    pd.read_csv(PATH + 'gxdc_gj20201223.csv'),
    pd.read_csv(PATH + 'gxdc_gj20201224.csv'),
    pd.read_csv(PATH + 'gxdc_gj20201225.csv')

])
bike_track = bike_track.sort_values(['BICYCLE_ID', 'LOCATING_TIME'])

bike_use_ratio = bike_track.groupby(['source','BICYCLE_ID', 'hour'])['date'].count() * 15.0 / 3615
bike_use_ratio = bike_use_ratio.reset_index()
bike_use_ratio.groupby(['source', 'hour'])['date'].mean()

统计结果:
source   hour
halou    6       0.157031
         7       0.221240
         8       0.315490
         9       0.223382
meituan  6       0.092250
         7       0.099389
         8       0.099104
         9       0.108867
qingju   6       0.054113
         7       0.161101
         8       0.195099
         9       0.120881
Name: date, dtype: float64

从统计结果我们可以看出哈喽单车的利用率是其中最高的,而且随着早高峰的到来变化也非常明显。其次是青桔单车,单车利用率也较高。表现最差的是美团单车,单车利用率较低,且在早高峰并没有充分利用。
在这里插入图片描述

调度衡量指标

对于共享单车利用率比较低的原因主要是单车调度不到位导致的,即在需要骑车的位置要有单车。这个过程就是单车调度的目标,在原始电单车分布的情况下对单车进行调度,让单车利用率变得更高。但是单车调度是存在成本的:

  • 每次调度的单车是有限的;
  • 每次调度的单车是存在时间成本;

调度具体的衡量因素包括:

  • 调度之后的单车的使用率;
  • 调度之后的停车点的潮汐情况;
  • 调度过程中的调度成本:
    • 调度单车个数;
    • 调度单车次数;

因此单车调度方法的优化指标可以写为:

在这里插入图片描述

单车调度算法

基于贪心思路的调度算法
基于遗传算法的调度算法

六、单车畅行友好度方案

geohash用一个字符串表示经度和纬度两个坐标。某些情况下无法在两列上同时应用索引 (例如MySQL 4之前的版本,Google App Engine的数据层等),利用geohash,只需在一列上应用索引即可。

其次,geohash表示的并不是一个点,而是一个矩形区域。比如编码wx4g0ec19,它表示的是一个矩形区域。 使用者可以发布地址编码,既能表明自己位于北海公园附近,又不至于暴露自己的精确坐标,有助于隐私保护。

  • 热力图展示中,用于geohash点聚合功能,可以提高大量点前端渲染的性能
  • 地址聚类中,通过geohash计算,进行地址归类
  • 地址信息缓存时,通过geohash为key,来索引缓存信息
import pandas as pd
import numpy as np
import glob

INPUT_PATH = '../input/' #文件目录
MAX_ROWS = None # 文件读取行数

taxiorder2019 = pd.read_csv(INPUT_PATH + 'taxiOrder20190531.csv', nrows=None,
                           dtype = {
                               'GETON_LONGITUDE': np.float32,
                               'GETON_LATITUDE': np.float32,
                               'GETOFF_LONGITUDE': np.float32,
                               'GETOFF_LATITUDE': np.float32,
                               'PASS_MILE': np.float16,
                               'NOPASS_MILE': np.float16,
                               'WAITING_TIME': np.float16
                           })


taxiorder2019['GETON_DATE'] = pd.to_datetime(taxiorder2019['GETON_DATE'])
taxiorder2019['GETOFF_DATE'] = pd.to_datetime(taxiorder2019['GETOFF_DATE'])

taxiorder2019 = taxiorder2019.rename(columns={'CAR_NO':'CARNO'})
taxiorder2019.sort_values(by=['CARNO','GETON_DATE'], inplace=True)
taxiorder2019.reset_index(inplace=True, drop=True)

# taxigps2019.apply(lambda x: geohash.encode(x['GETON_LATITUDE'], x['GETON_LONGITUDE'],  precision=5), axis=1)

taxiorder2019['geohash'] = taxiorder2019.apply(lambda x: geohash.encode(x['GETON_LATITUDE'], x['GETON_LONGITUDE'], precision=8), axis=1)
taxiorder2019['geohash'].value_counts().head(10)

'''
s0000000    6335
ws7unv0q     813
wsk584c9     745
ws7grb9s     617
ws7unv0r     608
wsk52k80     447
wsk584cd     416
ws7grbsy     409
ws7grb6d     394
wsk52dj9     362
Name: geohash, dtype: int64
'''

其中s0000000为经纬度异常点,可以剔除掉。接下来我们统计下热门经纬度的中心:

for idx in taxiorder2019['geohash'].value_counts().iloc[1:11].index:
    df = taxiorder2019[taxiorder2019['geohash'] == idx]
    print(idx, df['GETON_LONGITUDE'].mean(), df['GETON_LATITUDE'].mean())

'''
ws7unv0q 118.070595 24.637962
wsk584c9 118.127205 24.53685
ws7grb9s 118.116165 24.48105
ws7unv0r 118.07057 24.63811
wsk52k80 118.136154 24.502394
wsk584cd 118.1272 24.536997
ws7grbsy 118.12063 24.481407
ws7grb6d 118.11762 24.479357
wsk52dj9 118.15463 24.48881
wsk58ktu 118.14406 24.546976
'''

订单调度分析

巡游车根据等待时间统计具体位置:

legal_hash = taxiorder2019['geohash'].value_counts().iloc[:5000].index
taxiorder2019[taxiorder2019['geohash'].isin(legal_hash)].groupby(['geohash'])['WAITING_TIME'].mean().sort_values()

网约车根据等待时间统计具体位置:

wycorder2019['DEP_TIME'] = pd.to_datetime(wycorder2019['DEP_TIME'], format='%Y%m%d%H%M%S')
wycorder2019['BOOK_DEP_TIME'] = pd.to_datetime(wycorder2019['BOOK_DEP_TIME'], format='%Y%m%d%H%M%S')

wycorder2019['WAITING_TIME'] = (wycorder2019['DEP_TIME'] - wycorder2019['BOOK_DEP_TIME']).dt.seconds
wycorder2019['geohash'] = wycorder2019.apply(lambda x: geohash.encode(x['DEP_LATITUDE'], x['DEP_LONGITUDE'], precision=8), axis=1)
wycorder2019[wycorder2019['geohash'].isin(legal_hash)].groupby(['geohash'])['WAITING_TIME'].mean().sort_values()

通过统计发现,网约车与巡游车达不到车的位置区域存在部分重叠,但还是会有交叉的情况

  • 比如打不到网约车,也打不到出租车;
  • 比如打不到网约车,但能达到出租车;

在这里插入图片描述

  • 8
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浩波的笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值