内容介绍

梗概:求一个城市的公交的平均(非)直线系数,并结合前面博客所求得的公交线路的平均长度、平均站点数、平均站距,对比分析几个城市的公交路线基本数据。

准备知识

1、什么是“非直线系数”?(参考百度百科)
非直线系数是指道路起讫点间的实际交通距离与两点间空间直线距离之比。能评价不同的路网型式和客货流路线集散点之间联系的便捷程度。非直线系数:①棋盘式路网1.2〜1.4。②放射性路网一般在2.6左右。③环形加放射性路网一般为1.1〜1.2。

2、直线系数和非直线系数的区别:
本质上没区别,就是有的地方喜欢用"非直线系数"(大部分),有的地方称呼“直线系数”(少部分)。

3、求解难点——如何确定直线距离?

(1)先讲本博客认同的方法:求公交行车区间直线距离:
行车区间在代码中以"bounds"来表示,所谓行车区间不是始发站到终点站的距离!起码在高德地图的数据里不是,最开始我也搞错了,直到画出坐标对应图片才理解。个人感觉:所谓区间直线就是“对角线”的感觉,如图①把行车路径的最南,最西的点汇集成左下角一点,最北,最东一点汇集成右上角一点,然后将两点连线!

①青岛公交321路(环形线)路线和行车区间示意图

②青岛五条公交线路和对应区间直线

(2)求始发站到终点站的距离
这个是最主流的求公交直线的情况,很多政府性的报告中涉及到公交非直线系数也是以这种计算方法,许多关键指标的对照中的非直线系数仍然是以始发站到终点站的距离直线求出的。

但是,此方法不利于解决环形线路!!!!

倘若不处理环形线路,直接取始发站到终点站的距离(此时两者特别近),那么误差将会特别惊人。

本博客在处理的时候,采用的是判断线路中是否带有“环形”,来判断是否为环线,环形线路直线距离取值为始发站到中点站的距离*2
但效果并不理想!

因为,很多线路虽然不是严格意义上的环形线,但存在上下行!而且就算知道是环形线,但又不知道哪个两个站点之间位置距离最远!

总之,通过优化数据,排查错误,异常值检测,上下行、环形线路标定等办法,最后是能解决,但是,直接用获取到的区间来求直线距离不香吗?

(3)发散思维,多方法思考

①可以求所有相邻站点之间的直线距离,将它们累加起来。
缺点:这样求出的直线和路程长度差不多,参考意义并不是很大!

②求任意两个站点的之间的距离

站点数 2 3 4 5 6
所求直线数 1 3 6 10 15

即所求直线数为:n(n-1)/2,n为站点数

而且这样方法也不用求解任意两站之间的距离,只需要累加n(n-1)/2直线之后,除以总路程*(n-1)即可!

③还是采用始发站到终点站距离
这次也不专门判断是不是环形线路了,存不存在上下行,始发站和终点站是不是在一起,直接判断两者之间的距离,小于1km就认为始发站和终点站是一起的,然后,取始发站到中间站点距离*2为公交路线直线长度。
大规模数据情况下,不容易直接判断出一条线路哪两个点之间直线距离最长(非要求的话,可以采用“树的直径”问题类似算法解决,或者把始发站到所有站点直线求一遍,取最大那个),但是没必要,直接取始发站到中点距离即可,通常情况下,误差不会太大,在可接受范围内!

PS:
小于1km的通常都是始发站和终点站在一起的,而且通常是小于0.5km的,但也有例外:青岛19路(合肥路深圳路–汽车东站),行车区间有10多公里的情况下,始发站和终点站距离只有1.0695公里,属于始发站和终点站不在一块,但挨得特别近!


该进入正文了

1、排除环形线路

如果是英文的话,应该这么写也就好了

if '环形线' in dt['line_name']:print(dt['line_name'].find('环形'))

但是,中文的话,判断子字符串或许会麻烦一点。

我这里具体也没上网查,写了个下面的版本

        #特判是不是环形线tmp=[]for i in dt['line_name']:tmp.append(i)for i in range(0,len(tmp)):if tmp[i]=='环' and tmp[i+1]=='行':print(dt['line_name'])dt['straight']=dt['straight']*2 #环形线直线距离乘2lng1,lat1 = rt['buslines'][0]['busstops'][0]['location'].split(',')  #始发站坐标lng2,lat2 = rt['buslines'][0]['busstops'][int(dt['station']/2)]['location'].split(',') #中间站坐标dt['straight2'] = Geodistance(float(lng1),float(lat1),float(lng2),float(lat2))*2 #始发站到中间站点距离且需要*2

确实能判断出名字中带有环形的线路(两条321路,是因为一个是正常线路,一个是定时区间的车)

2、处理上下行
以上是早期处理直线的思路,后发现有大量的上下行问题没法解决,故采取
直接判断始发站到终点站之间的距离的办法,小于1km就认为始发站和终点站是一起的。

这个判断就比前面那个容易了,非要说说代码,求解始发站到中间站点直线距离思路挺巧妙的~

        if  dt['straight2']<1.0:print(dt['line_name'])dt['straight']=dt['straight']*2 #环形线直线距离乘2lng1,lat1 = rt['buslines'][0]['busstops'][0]['location'].split(',')  #始发站坐标lng2,lat2 = rt['buslines'][0]['busstops'][int(dt['station']/2)]['location'].split(',') #中间站坐标dt['straight2'] = Geodistance(float(lng1),float(lat1),float(lng2),float(lat2))*2 #始发站到中间站点距离且需要*2

3、直接可运行的汇总代码
改了挺多版本的,事后看起来挺简单的,但当时解决问题的过程确实走了不少弯路。

import requests
import json
import pandas as pd
import time
from math import sin, asin, cos, radians, sqrt#python计算两点间直线距离
def Geodistance(lng1,lat1,lng2,lat2):lng1, lat1, lng2, lat2 = map(radians, [lng1, lat1, lng2, lat2])dlon=lng2-lng1dlat=lat2-lat1a=sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2 dis=2*asin(sqrt(a))*6371*1000return dis/1000  #换算为千米#获取公交信息:线路名、行车区间(坐标)、路程、行车区间直线距离等
def Bus_inf(city,line):global bus_num  #全局变量,用于计算公交数目try:#获取数据url = 'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=a5b7479db5b24fd68cedcf24f482c156&output=json&city={}&offset=1&keywords={}&platform=JS'.format(city,line)r = requests.get(url).textrt = json.loads(r)#读取当前公交线路基本信息dt = {}dt['line_name'] = rt['buslines'][0]['name'] #公交线路名字dt['bounds'] = rt['buslines'][0]['bounds'] #行车区间(不是始发站,终点站坐标!!!)dt['distance'] = float(rt['buslines'][0]['distance']) #全程长度dt['station'] = int(rt['buslines'][0]['busstops'][-1]['sequence']) #全程站点数(包括始发站和终点站)dt['station_dis'] = dt['distance']/(dt['station']-1) #该路线站距#计算直线系数 和 非直线系数=1/直线系数#以下为两套求直线的方法:(1)求行车区间 (2)求始发站到终点站距离lng1,lat1 =rt['buslines'][0]['bounds'].split(';')[0].split(',')  lng2,lat2 =rt['buslines'][0]['bounds'].split(';')[1].split(',')  dt['straight'] =  Geodistance(float(lng1),float(lat1),float(lng2),float(lat2)) #计算区间bounds的直线距离lng1,lat1 = rt['buslines'][0]['busstops'][0]['location'].split(',')  #始发站坐标lng2,lat2 = rt['buslines'][0]['busstops'][-1]['location'].split(',') #终点站坐标dt['straight2'] =  Geodistance(float(lng1),float(lat1),float(lng2),float(lat2)) #始发站到终点站的直线距离#首尾距离小于1km即认为存在上下行(环形线路)if  dt['straight2']<1.0:print(dt['line_name'])dt['straight']=dt['straight']*2 #环形线直线距离乘2lng1,lat1 = rt['buslines'][0]['busstops'][0]['location'].split(',')  #始发站坐标lng2,lat2 = rt['buslines'][0]['busstops'][int(dt['station']/2)]['location'].split(',') #中间站坐标dt['straight2'] = Geodistance(float(lng1),float(lat1),float(lng2),float(lat2))*2 #始发站到中间站点距离且需要*2dt['straight_dis'] = dt['straight']/dt['distance']      #直线系数1=直线长度/路程长度 (0,1]dt['non_straight_dis'] = dt['distance']/dt['straight']  #非直线系数1=路程长度/直线长度 [1,∞)dt['straight_dis2'] = dt['straight2']/dt['distance']      #直线系数2=直线长度/路程长度 (0,1]dt['non_straight_dis2'] = dt['distance']/dt['straight2']  #非直线系数2=路程长度/直线长度 [1,∞)bus_num+=1 #有效公交数+1return pd.DataFrame(dt,index=[bus_num]) #下标index为“第几条公交线”except:#print('没有{}公交'.format(line)) #正常情况下,这条语句不会执行return pd.DataFrame()  #读取数据失败,返回空的def Bus_analysis(bus_info):print('公交线路的平均长度:{:.6f} km'.format(bus_info["distance"].mean())) print('公交线路的平均站点数:{:.6f} 个'.format(bus_info['station'].mean()))print('公交线路的平均站距1为:{:.6f} km/站'.format(bus_info["distance"].sum()/(bus_info['station'].sum()-bus_num)))print('公交线路的平均直线系数(区间距离):{:.6f}'.format(bus_info['straight'].sum()/bus_info["distance"].sum()))print('公交线路的平均非直线系数(区间距离):{:.6f}'.format(bus_info["distance"].sum()/bus_info['straight'].sum()))print('公交线路的平均直线系数(首位距离):{:.6f}'.format(bus_info['straight2'].sum()/bus_info["distance"].sum()))print('公交线路的平均非直线系数(首位距离):{:.6f}'.format(bus_info["distance"].sum()/bus_info['straight2'].sum()))if __name__=="__main__":t0=time.time()bus_num=0  #设置全局变量数值(通常默认就是0)city='青岛' #需要查询公交信息的城市for_num=1000 #遍历的线路数[1路,for_num路],通常公交线路数小于1000,具体可参考8684等网站all_buslines=pd.DataFrame()     for i in range(1,for_num+1):all_buslines=pd.concat([all_buslines,Bus_inf(city,str(i)+'路')])  #不加这个'路'可能优先获取地铁print("Bus_info函数遍历{}前{}路公交,有效公交线路数为:{}个的情况下:".format(city,for_num,bus_num))Bus_analysis(all_buslines)all_buslines.to_csv("{}前{}路公交(有效线路数:{})基本信息.csv".format(city,for_num,bus_num),encoding='utf-8-sig')t1=time.time()print("用时:%.2fs"%(t1-t0))

查找始发站和终点站在一起的能力还挺不错的!

4、读取文本路线名的主函数
记得Bus_analysis(all_buslines,len(bus_name))要加一个bus_num变量,其他就和上面一样了

if __name__=="__main__":record_time(0)all_buslines=pd.DataFrame()city='青岛市'#获取已知线路的公交文本with open("公交线路.txt", "r", encoding="utf-8") as f:bus_name = f.readlines()bus_name = bus_name[0].split(",") for i in bus_name:  all_buslines=pd.concat([all_buslines,Bus_inf(city,i)]) Bus_analysis(all_buslines,len(bus_name))print("通过文本获取青岛市区{}条路线基本信息成功!".format(len(bus_name)))all_buslines.to_csv("通过文本获取的青岛市区{}条路线基本信息.csv".format(len(bus_name)),index=False,encoding='utf-8-sig')record_time(1)

对比分析

在前面的实验内容中,我们通过处理各种问题,最终掌握了计算出一个城市公交线路平均长度、平均站点数、平均站距、平均直线系数的方法。下面通过循环一个城市前1000路公交,对比分析一下它们的平均参数,其中关于直线系数,选取了“区间直线”和“始发站到终点站”直线(首尾直线)两种情况

关于直接循环1000路这个方法的补充说明:这个方法确实存在会遗漏一些线路的情况,但我们可以理解为这是“随机取样”的结果,一个城市前1000路公交中存在的线路,已经基本能反映其公交特征,而且遗漏的线路往往都是一些不符合标准城市公交特征的专线。另外,一个城市前1000路公交的有效公交数,也能侧面反映其城市规模。

青岛市区线路和全市线路对比
下图分别为青岛全市获取的423条线路,及市区256条线路的实验结果。可见,市区线路点与点之间联系比较频繁,其平均站点数会较多一点,平均站点会更短一点。但由于所处地理环境等因素的影响,其非直线系数相差并不多。


一线城市公交线路基本特征分析

北京市前1000路有效公交数为768个,深圳市前1000路有效公交数为821个,足以侧面看出一线城市的交通体量之大。城市规模大,线路平均长度也随之变大,但考虑到深圳是城市化率100%的一线新兴城市,其公交平均站距会较北京少了不少。


其他城市对比
厦门市是五大经济特区之一,面积大约是青岛的八分之一,地方不大,平均公交线路自然不长,线路平均站点数也比较少。

三明市是一个地处福建丘陵,森林绿化率全国第一的一个小城市,其公交基本特征见下图,可知,其公交线路长度一般都不太长,平均站距也会比上面大城市短一些。


三明路线分布图,以河流两侧的长直线为主,所以直线系数还是比较高的

说明

因为求解直线系数中的“直线‘没法准确获得,且不能保证获取公交数据的完整性,上面所得的城市公交”非直线系数“等结果是存在误差的,请大家酌情参考。


这个系列博客原计划是还有公交换乘网络构建和分析的

但突然不想写了,复习考研去了ㄟ( ▔, ▔ )ㄏ

至此《城市公交网络分析与可视化》系列博客告一段落!

【大数据】城市公交网络分析与可视化(六):对比分析不同城市公交的“非直线系数”相关推荐

  1. 【大数据】城市公交网络分析与可视化(五):获取公交平均路线长度、站点数、站距

    内容简介 也不前情提要了,本博客内容高度概括就是:通过直接遍历法和依据文本法获取一个城市的"所有"线路名,并计算这些线路的平均路线长度.平均站点数.平均站距("直线系数& ...

  2. 【大数据】城市公交网络分析与可视化(三):获取公交站点信息并可视化站点重要程度

    博客内容简介 通过前面的探究,我们大体知道如何获取一个城市的公交数据,并绘制了公交行驶路径散点图(效果不是很理想). 其实散点图感觉更适合类似于绘制公交站点这样的信息(行驶轨迹有其他更好的绘制技巧), ...

  3. 【大数据课程设计】城市公交网络分析与可视化(以青岛市为例)

    城市公交网络 城市公交网络分析与可视化 数据爬取与处理 公交站点信息爬取 公交线路轨迹爬取 坐标转换 城市公交网络可视化 利用ArcMap实现地图的可视化 利用plotly实现地图可视化 公交路线基本 ...

  4. 基于大数据的智能网络分析

    2018云栖大会深圳峰会弹性计算.网络和CDN专场上,阿里云高级技术专家云州给大家一起探讨了大数据的智能网络分析.通过介绍全球网络的超大规模,进而说明了智能网络齐天的设计必要性,着重详讲解了齐天智能网 ...

  5. Py之pyecharts:基于大数据对人工智能进行各种可视化图表分析

    pyecharts:基于大数据对人工智能进行各种可视化图表分析 目录 1. Bar(柱状图/条形图) 2 EffectScatter(带有涟漪特效动画的散点图) 3 .Funnel(漏斗图) 4.Ga ...

  6. 基于大数据的动漫影视可视化分析系统

    温馨提示:文末有 CSDN 平台官方提供的学长 Wechat / QQ 名片 :) 1. 项目简介 本动漫分析系统开发语言为Python,并进行数据清洗,数据处理,并最后利用可视化技术进行动漫数据分析 ...

  7. 一口气实现交通大数据爬取与Python可视化(含数据分享)

    今天的文章呢主要目的不是爬虫,而是爬虫的同时顺便实现实时可视化.上次爬摩拜单车数据的文章使用的是传统的ArcGIS进行自定义可视化,硬核 | Python多线程爬取摩拜单车数据与ArcGIS可视化,今 ...

  8. 【大数据入门笔记系列】第六节 分布式计算框架MapReduce的工作流程

    [大数据入门笔记系列]第六节 分布式计算框架MapReduce的工作流程 前言 MapReduce分布式运算 MapReduceApplication MapTask ReduceTask split ...

  9. “容灾大数据城”梧桐引来金凤凰,千万元融资助“城市大脑”起步

    看什么看,快点蓝字关注我! 这边深圳"智博会"还未落幕,那边重庆"智博会"已经鸣锣开场.两个大会虽然定位.内容不完全相同,但同一个"智"字再 ...

最新文章

  1. Kaggle冠军经验分享丨如何用15个月冲到排行榜的首位
  2. IOS之--UI进阶--多控制器管理第一天
  3. 【.Net MF网络开发板研究-01】IP地址设定及简单web演示
  4. 操作 Wave 文件(4): 获取 Wave 文件主块与子块的信息
  5. 2015年山石网科面试题
  6. SAP CRM中间件下载equipment时遇到的一个错误
  7. 云智能遥控开关设备再物联网领域的应用:智能养殖高效、生态、安全!
  8. 1005:I Think I Need a Houseboat-poj
  9. 邓总的vim配置,需要的自己拿走~
  10. xampp 支持pdo mysql_在Windows上安装PHP PDO(xampp)
  11. python中的zip是什么意思_Python的zip()函数是什么
  12. vue-cli脚手架中webpack配置基础文件详解
  13. 配置windows 2003 ×××服务器
  14. window下连接ubuntu mysql的问题
  15. 华师大版数学分析下知识点总结
  16. windows10应用商店下安装kali子系统
  17. c# Dll反编译查看原文件
  18. 战胜25名医生:AI真能成为医疗界的“擂主”?
  19. oracle同义词表不存在,同义词什么时候失效呢?
  20. 这程序还厉害的。。。

热门文章

  1. 海尔电视android怎么设置,海尔电视怎么连接手机 海尔电视连接手机步骤
  2. 不用中间变量实现strlen函数
  3. 计算机毕业设计Node.js+Vue房地产销售系统(程序+源码+LW+部署)
  4. 用歌词来记录此时的心情
  5. a50指数你知道吗,富时指数之A50指数
  6. 计算机毕业论文选题微信小程序毕业设计论文ssm便捷记账本小程序+后台管理系统|前后分离VUE[包运行成功]
  7. 计算机网络复习——第四章:网络层——数据平面
  8. DFS递归之岛屿问题
  9. 企业应用程序安全的新「守护神」
  10. 数据归约——主成分分析PCA