數(shù)據(jù)獲取自高德地圖API,包含了天津市公交線路和站點名稱及其經緯度數(shù)據(jù)。
import?pandas?as?pd df?=?pd.read_excel('site_information.xlsx') df.head()
字段說明:
線路名稱:公交線路的名稱
上下行:0表示上行;1表示下行
站序號:公交線路上行或下行依次經過站的序號
站名稱:站點名稱
經度(分):站點的經度
緯度(分):站點的緯度
數(shù)據(jù)字段少,結構也比較簡單,下面來充分了解我們的數(shù)據(jù)和進行預處理。
總的數(shù)據(jù)有 30396 條,站名稱缺失了 5 條,緯度(分)缺失了 1 條,經度(分)缺失了 38 條,為了處理方便,直接把有缺失值的行刪除。
經緯度數(shù)據(jù)是7031.982、2348.1016這樣的,需要將其轉換為以度為單位。
df2?=?df1.copy() df2['經度(分)']?=?df1['經度(分)'].apply(float)?/?60 df2['緯度(分)']?=?df1['緯度(分)'].apply(float)?/?60 df2.head()
處理后的數(shù)據(jù)里,共有 618 條公交線路,4851個站點數(shù)據(jù)。
重新保存為處理后數(shù)據(jù)
df2.to_excel("處理后數(shù)據(jù).xlsx",?index=False)二、數(shù)據(jù)分析
分析天津市公交站點的分布情況
#?-*-?coding:?UTF-8?-*- """ import?pandas?as?pd import?matplotlib.pyplot?as?plt import?matplotlib?as?mpl import?random df?=?pd.read_excel("處理后數(shù)據(jù).xlsx") x_data?=?df['經度(分)'] y_data?=?df['緯度(分)'] colors?=?['#FF0000',?'#0000CD',?'#00BFFF',?'#008000',?'#FF1493',?'#FFD700',?'#FF4500',?'#00FA9A',?'#191970',?'#9932CC'] colors?=?[random.choice(colors)?for?i?in?range(len(x_data))] mpl.rcParams['font.family']?=?'SimHei' plt.style.use('ggplot') #?設置大小 plt.figure(figsize=(12,?6),?dpi=200) #?繪制散點圖??經度??緯度??傳進去???設置?顏色??點的大小 plt.scatter(x_data,?y_data,?marker="o",?s=9.,?c=colors) #?添加描述信息?x軸?y軸?標題 plt.xlabel("經度") plt.ylabel("緯度") plt.title("天津市公交站點分布情況") plt.savefig('經緯度散點圖.png') plt.show()
結果如下:
通過 matplotlib 繪制散點圖可視化天津市公交站點的分布情況,容易看出天津市的公交熱點分布區(qū)域。為了能更形象地分析公交線路網絡,我們可以將數(shù)據(jù)可視化在實際地圖上,利用 Pyecharts 的BMap。
#?-*-?coding:?UTF-8?-*- """ import?pandas?as?pd from?pyecharts.charts?import?BMap from?pyecharts?import?options?as?opts from?pyecharts.globals?import?CurrentConfig #?引用本地js資源渲染 CurrentConfig.ONLINE_HOST?=?'D:/python/pyecharts-assets-master/assets/' df?=?pd.read_excel('處理后數(shù)據(jù).xlsx',?encoding='utf-8') df.drop_duplicates(subset='站名稱',?inplace=True) longitude?=?list(df['經度(分)']) latitude?=?list(df['緯度(分)']) datas?=?[] a?=?[] for?i,?j?in?zip(longitude,?latitude): ????a.append([i,?j]) datas.append(a) print(datas) BAIDU_MAP_AK?=?"改成你的百度地圖AK" c?=?( ????BMap(init_opts=opts.InitOpts(width="1200px",?height="800px")) ????.add_schema( ????????baidu_ak=BAIDU_MAP_AK,?????#?申請的BAIDU_MAP_AK ????????center=[117.20,?39.13],????#?天津市經緯度中心 ????????zoom=10, ????????is_roam=True, ????) ????.add( ????????"", ????????type_="lines", ????????is_polyline=True, ????????data_pair=datas, ????????linestyle_opts=opts.LineStyleOpts(opacity=0.2,?width=0.5,?color='red'), ????????#?如果不是最新版本的話可以注釋下面的參數(shù)(效果差距不大) ????????progressive=200, ????????progressive_threshold=500, ????) ) c.render('公交網絡地圖.html')
結果如下:
在地圖上可以看到,和平區(qū)、南開區(qū)公交線路網絡密集,交通便利。
公交線路網絡中 i 節(jié)點代表第 i 條線路,其中節(jié)點 i 的度定義為與線路 i 可以經過換乘能夠到達的線路的數(shù)目,線路網絡的度大小反映了該條公交線路與其他線路的連通程度,構建算法分析公交線路網絡度的分布。
#?-*-?coding:?UTF-8?-*- """ import?xlrd import?matplotlib.pyplot?as?plt import?pandas?as?pd import?matplotlib?as?mpl df?=?pd.read_excel("site_information.xlsx") #?用pandas的操作去重???得到每條線路的名稱 loc?=?df['線路名稱'].unique() #?得到每一條線路名稱的列表 line_list?=?list(loc) print(line_list) #?打開Excel表格 data?=?xlrd.open_workbook("site_information.xlsx") #?print(data)???#??在內存中 #?獲取特定Sheet??索引為0??也就是第一個表 table?=?data.sheets()[0]??#?從零開始 #?每條線路對應有哪些站點??字典推導式 site_dic?=?{k:?[]?for?k?in?line_list} site_list?=?[] for?i?in?range(1,?table.nrows): ????#?每一行的數(shù)據(jù)???返回的是一個列表 ????x?=?table.row_values(i) ????if?x[1]?==?"0": ????????#?上行???站點數(shù)據(jù)??每條線路對應有哪些站點?添加進列表 ????????site_dic[x[0]].append(x[3]) ????????site_list.append(x[3]) ????else: ????????continue #?print(len(site_dic))???#?618條線路 #?print(len(site_list))??#?15248條站點數(shù)據(jù) print(f"公交網絡共有?{len(line_list)}?條線路")???#?618條線路 #?先初始化一個統(tǒng)計每個節(jié)點的度的列表??與線路名稱列表里的索引一一對應 node_count?=?[m?*?0?for?m?in?range(len(line_list))] #?以每條線路為一個節(jié)點??線路名稱為鍵??????值為一個列表??里面包含每條路線上行經過的所有站點 sites?=?[site?for?site?in?site_dic.values()] #?print(sites) for?j?in?range(len(sites)):??#?類似冒泡法排序??比較多少趟 ????for?k?in?range(j,?len(sites)?-?1):??#?每趟比較后??往后推一個??直到比較完??和防止越界 ????????if?len(sites[j])?>?len(sites[k?+?1]): ????????????for?x?in?sites[j]: ????????????????if?x?in?sites[j]?and?x?in?sites[k?+?1]:???#?只要這兩條線路有公共站點??節(jié)點度數(shù)加1 ????????????????????node_count[j],?node_count[k?+?1]?=?node_count[j]?+?1,?node_count[k?+?1]?+?1 ????????????????????break???#?兩條線路對應在列表索引的值加1???這兩條線的比較結束 ????????else: ????????????for?x?in?sites[k?+?1]: ????????????????if?x?in?sites[j]?and?x?in?sites[k?+?1]:???#?只要這兩條線路有公共站點??節(jié)點度數(shù)加1 ????????????????????node_count[j],?node_count[k?+?1]?=?node_count[j]?+?1,?node_count[k?+?1]?+?1 ????????????????????break???#?兩條線路對應在列表索引的值加1???這兩條線的比較結束 #?print(node_count) #?節(jié)點編號?與?節(jié)點的度數(shù)索引對應 node_number?=?[y?for?y?in?range(len(node_count))] #?線性網絡度的最大值???175 print(f"線路網絡的度的最大值為:{max(node_count)}") print(f"線路網絡的度的最小值為:{min(node_count)}") print(f"線路網絡的度的平均值為:{sum(node_count)?/?len(node_count)}") #?設置大小??圖的像素 #?設置字體???matplotlib?不支持顯示中文??自己本地設置 plt.figure(figsize=(10,?6),?dpi=150) mpl.rcParams['font.family']?=?'SimHei' #?繪制每個節(jié)點度的分布 plt.bar(node_number,?node_count,?color="purple") #?添加描述信息 plt.xlabel("節(jié)點編號n") plt.ylabel("節(jié)點的度數(shù)K") plt.title("線路網絡中各節(jié)點的度的大小分布",?fontsize=15) plt.savefig("線路網絡中各節(jié)點的度的大小.png") plt.show()
結果如下:
公交網絡共有 618 條線路
線路網絡的度的最大值為:175
線路網絡的度的最小值為:0
線路網絡的度的平均值為:55.41423948220065
import?xlrd import?matplotlib.pyplot?as?plt import?pandas?as?pd import?matplotlib?as?mpl import?collections df?=?pd.read_excel("site_information.xlsx") #?用pandas的操作去重???得到每條線路的名稱 loc?=?df['線路名稱'].unique() #?得到每一條線路名稱的列表 line_list?=?list(loc) print(line_list) #?打開Excel表格 data?=?xlrd.open_workbook("site_information.xlsx") #?print(data)???#??在內存中 #?獲取特定Sheet??索引為0??也就是第一個表 table?=?data.sheets()[0]??#?從零開始 #?每條線路對應有哪些站點??字典推導式 site_dic?=?{k:?[]?for?k?in?line_list} site_list?=?[] for?i?in?range(1,?table.nrows): ????#?每一行的數(shù)據(jù)???返回的是一個列表 ????x?=?table.row_values(i) ????if?x[1]?==?"0": ????????#?上行???站點數(shù)據(jù)??每條線路對應有哪些站點?添加進列表 ????????site_dic[x[0]].append(x[3]) ????????site_list.append(x[3]) ????else: ????????continue #?print(len(site_dic))???#?618條線路 #?print(len(site_list))??#?15248條站點數(shù)據(jù) #?先初始化一個統(tǒng)計每個節(jié)點的度的列表??與線路名稱列表里的索引一一對應 node_count?=?[m?*?0?for?m?in?range(len(line_list))] #?以每條線路為一個節(jié)點??線路名稱為鍵??????值為一個列表??里面包含每條路線上行經過的所有站點 sites?=?[site?for?site?in?site_dic.values()] #?print(sites) for?j?in?range(len(sites)):??#?類似冒泡法排序??比較多少趟 ????for?k?in?range(j,?len(sites)?-?1):??#?每趟比較后??往后推一個??直到比較完??和防止越界 ????????if?len(sites[j])?>?len(sites[k?+?1]): ????????????for?x?in?sites[j]: ????????????????if?x?in?sites[j]?and?x?in?sites[k?+?1]:???#?只要這兩條線路有公共站點??節(jié)點度數(shù)加1 ????????????????????node_count[j],?node_count[k?+?1]?=?node_count[j]?+?1,?node_count[k?+?1]?+?1 ????????????????????break???#?兩條線路對應在列表索引的值加1???這兩條線的比較結束 ????????else: ????????????for?x?in?sites[k?+?1]: ????????????????if?x?in?sites[j]?and?x?in?sites[k?+?1]:???#?只要這兩條線路有公共站點??節(jié)點度數(shù)加1 ????????????????????node_count[j],?node_count[k?+?1]?=?node_count[j]?+?1,?node_count[k?+?1]?+?1 ????????????????????break???#?兩條線路對應在列表索引的值加1???這兩條線的比較結束 #?print(node_count) #?節(jié)點編號?與?節(jié)點的度數(shù)索引對應 node_number?=?[y?for?y?in?range(len(node_count))] #?線性網絡度的最大值???175 #?print(max(node_count)) #?設置大小??圖的像素 #?設置字體???matplotlib?不支持顯示中文??自己本地設置 plt.figure(figsize=(10,?6),?dpi=150) mpl.rcParams['font.family']?=?'SimHei' #?分析節(jié)點的度K的概率分布 #?統(tǒng)計節(jié)點的度為K的?分別有多少個 node_count?=?collections.Counter(node_count) node_count?=?node_count.most_common() #?點 node_dic?=?{_k:?_v?for?_k,?_v?in?node_count} #?按鍵從小到大排序???得到一個列表??節(jié)點的度 sort_node?=?sorted(node_dic) #?按順序得到鍵對應的值???即有相同節(jié)點的度的個數(shù) sort_num?=?[node_dic[q]?for?q?in?sort_node] #?概率分布中度平均值??總的度數(shù)加起來??/?個數(shù) #?print(sum(sort_node)/len(sort_node)) #?概率分布中最大的度值???也就個數(shù)最多那個 print(f"概率分布中概率最大的度值為:{max(sort_num)}") probability?=?[s1?/?sum(sort_num)?for?s1?in?sort_num]???#?概率分布 print(probability) #?天津市公交線路節(jié)點概率分布圖像 plt.bar(sort_node,?probability,?color="red") #?添加描述信息 plt.xlabel("節(jié)點的度K") plt.ylabel("節(jié)點度為K的概率P(K)") plt.title("線路網絡中節(jié)點度的概率分布",?fontsize=15) plt.savefig("線路網絡中節(jié)點度的概率分布.png") plt.show()
結果如下:
概率分布中概率最大的度值為:16
天津市公交線路網絡的度分布如上圖所示,本文收集的天津市線路網絡共有 618 條線路組成,線路網絡的度的最大值為175。概率分布中概率最大的度值為16,度平均值為55.41,表明天津市公交網絡提供的換乘機會較多,使得可達性較高。其中概率較大的度值大多集中在 7~26 之間。使得節(jié)點強度分布相對來說不夠均勻,造成天津市很多路段公交線路較少,少數(shù)路段經過線路過于密集,造成資源的浪費。
聚類系數(shù)是研究節(jié)點鄰居之間的連接緊密程度,因此不必考慮邊的方向。對于有向圖,將其當成無向圖來處理。網絡聚類系數(shù)大,表明網絡中節(jié)點與其附近節(jié)點之間的連接緊密度程度高,即與實際站點之間的公交線路連接密集。計算得到天津公交復雜網絡的聚類系數(shù)為0.091,相對其他城市較低。
根據(jù)公式:
同規(guī)模的隨機網絡聚集系數(shù)約為0.00044,進一步體現(xiàn)了網絡的小世界特性。
import?xlrd import?matplotlib.pyplot?as?plt import?pandas?as?pd import?matplotlib?as?mpl #?讀取數(shù)據(jù) df?=?pd.read_excel("site_information.xlsx") #?用pandas的操作去重???得到每條線路的名稱 loc?=?df['線路名稱'].drop_duplicates() #?得到每一條線路名稱的列表??按照Excel表里以次下去的順序 line_list?=?list(loc) #?print(line_list) #?打開Excel表格 data?=?xlrd.open_workbook("site_information.xlsx") #?print(data)???#??在內存中 #?獲取特定Sheet??索引為0??也就是第一個表 table?=?data.sheets()[0]??#?從零開始 #?每條線路對應有哪些站點??字典推導式 site_dic?=?{k:?[]?for?k?in?line_list} site_list?=?[] for?i?in?range(1,?table.nrows): ????#?每一行的數(shù)據(jù)???返回的是一個列表 ????x?=?table.row_values(i) ????if?x[1]?==?"0": ????????#?只取上行站點數(shù)據(jù)??每條線路對應有哪些站點?添加進列表 ????????site_dic[x[0]].append(x[3]) ????????site_list.append(x[3]) ????else: ????????continue #?print(len(site_dic))???#?618條線路 #?print(len(site_list))??#?15248條站點數(shù)據(jù) #?先初始化一個統(tǒng)計每個節(jié)點的度的列表??與線路名稱列表里的索引一一對應 node_count?=?[m?*?0?for?m?in?range(len(line_list))] #?以每條線路為一個節(jié)點??線路名稱為鍵??????值為一個列表??里面包含每條路線上行經過的所有站點 sites?=?[site?for?site?in?site_dic.values()] #?print(sites) #?統(tǒng)計各節(jié)點的度 for?j?in?range(len(sites)?-?1):??#?類似冒泡法排序??比較多少趟 ????for?k?in?range(j,?len(sites)?-?1):??#?每趟比較后??往后推一個??直到比較完??和防止越界 ????????if?len(sites[j])?>?len(sites[k?+?1]): ????????????for?x?in?sites[j]: ????????????????if?x?in?sites[j]?and?x?in?sites[k?+?1]:???#?只要這兩條線路有公共站點??節(jié)點度數(shù)加1 ????????????????????node_count[j],?node_count[k?+?1]?=?node_count[j]?+?1,?node_count[k?+?1]?+?1 ????????????????????break???#?兩條線路對應在列表索引的值加1???這兩條線的比較結束 ????????else: ????????????for?x?in?sites[k?+?1]: ????????????????if?x?in?sites[j]?and?x?in?sites[k?+?1]:???#?只要這兩條線路有公共站點??節(jié)點度數(shù)加1 ????????????????????node_count[j],?node_count[k?+?1]?=?node_count[j]?+?1,?node_count[k?+?1]?+?1 ????????????????????break???#?兩條線路對應在列表索引的值加1???這兩條線的比較結束 #?找到該節(jié)點的鄰居節(jié)點??鄰居節(jié)點間實際的邊數(shù) Ei?=?[] #?對每條線路進行找鄰接節(jié)點??并統(tǒng)計其鄰接節(jié)點點實際的邊數(shù) for?a?in?range(len(sites)): ????neighbor?=?[] ????if?node_count[a]?==?0: ????????Ei.append(0) ????????continue ????if?node_count[a]?==?1: ????????Ei.append(0) ????????continue ????for?b?in?range(len(sites)): ????????if?a?==?b:????#?自身??不比 ????????????continue ????????if?len(sites[a])?>?len(sites[b]):???#?從站點多的線路里選取站點???看是否有公共站點 ????????????for?x?in?sites[a]: ????????????????if?x?in?sites[a]?and?x?in?sites[b]:??#?找到鄰居節(jié)點 ????????????????????neighbor.append(sites[b]) ????????????????????break ????????else: ????????????for?x?in?sites[b]: ????????????????if?x?in?sites[a]?and?x?in?sites[b]:??#?找到鄰居節(jié)點 ????????????????????neighbor.append(sites[b]) ????????????????????break ????#?在鄰居節(jié)點中判斷這些節(jié)點的實際邊數(shù)??又類似前面的方法??判斷兩兩是否相連 ????count?=?0 ????for?c?in?range(len(neighbor)?-?1): ????????for?d?in?range(c,?len(neighbor)?-?1):??#?每趟比較后??往后推一個??直到比較完??和防止越界 ????????????try: ????????????????if?len(sites[c])?>?len(sites[d?+?1]): ????????????????????for?y?in?sites[c]: ????????????????????????if?y?in?sites[c]?and?y?in?sites[d?+?1]:??#?鄰居節(jié)點這兩個也相連 ????????????????????????????count?+=?1 ????????????????????????????break ????????????????????????else: ????????????????????????????continue ????????????????else: ????????????????????for?y?in?sites[d?+?1]: ????????????????????????if?y?in?sites[c]?and?y?in?sites[d?+?1]:??#?鄰居節(jié)點這兩個也相連 ????????????????????????????count?+=?1 ????????????????????????????break ????????????????????????else: ????????????????????????????continue ????????????except?IndexError: ????????????????break ????Ei.append(count) #?每個節(jié)點的鄰居節(jié)點間實際相連的邊數(shù) #?print(Ei) #?節(jié)點編號?與?節(jié)點的度數(shù)索引對應 node_number?=?[y?for?y?in?range(len(node_count))] #?設置字體???matplotlib?不支持顯示中文??自己本地設置 mpl.rcParams['font.family']?=?'SimHei' #?設置大小??圖的像素 plt.figure(figsize=(10,?6),?dpi=150) #?公交線路網絡的聚類系數(shù)分布圖像???相鄰節(jié)點的連通程度 Ci?=?[] for?m?in?range(len(node_number)): ????if?node_count[m]?==?0: ????????Ci.append(0) ????elif?node_count[m]?==?1: ????????Ci.append(0) ????else:??#?2?*?該節(jié)點鄰居節(jié)點實際連接邊數(shù)?/?最大邊數(shù) ????????Ci.append(2?*?Ei[m]?/?(node_count[m]?*?(node_count[m]?-?1))) #?各節(jié)點鄰居節(jié)點的連通程度?計算平均聚類系數(shù) print("天津市公交線路網絡平均聚類系數(shù)為:{:.4f}".format(sum(Ci)?/?len(Ci))) plt.bar(node_number,?Ci,?color="blue") #?添加描述信息 plt.xlabel("節(jié)點編號n") plt.ylabel("節(jié)點的聚類系數(shù)") plt.title("線路網絡中各節(jié)點的聚類系數(shù)分布",?fontsize=15) plt.savefig("聚類系數(shù)分布.png") plt.show()
結果如下:
天津市公交線路網絡平均聚類系數(shù)為:0.0906