iT邦幫忙

1

[Python]專題P01─臺灣春節國道預估塞車時間準不準?

Hi! 大家好久不見,我是Eric。真的是時隔多日,我們的網站終於又更新啦!這次要練習運用Python中的matplotlib套件來做一個小專題,繼續來看下去/images/emoticon/emoticon82.gif


[緣起] :每逢春節過年,高速公路局都會提前公布國道預估塞車的時段給大家參考,那到底準不準呢?這次,我們就要來用Python來檢驗看看。這次要看的是最近3年(2019-2021)的初一。

2019年初一預估塞車時段最久的是南下竹北-新竹(07:30-13:30),如下圖:
https://ithelp.ithome.com.tw/upload/images/20210820/20115774J7VKILYlDG.jpg

2020年(X) Covid19年(O) 初一預估塞車時段最久的是南下南港系統-石碇(06:00-16:30),如下圖:
https://ithelp.ithome.com.tw/upload/images/20210820/20115774wZXah4RF8q.jpg
資料來源:交通部高速公路局

2021年初一預估塞車時段最久的是一樣是南下南港系統-石碇(05:30-15:30),如下圖:
https://ithelp.ithome.com.tw/upload/images/20210820/20115774XB0joH7P6r.jpg
資料來源:大年初一下午再出門 記得避開國道六大地雷路段(2020-01-24 15:38:12聯合報 記者侯俐安/台北即時報導)

[方法] :運用[Python]的[pandas、matplotlib]套件。
[使用資料] :交通部高速公路局交通資料庫ETC(Electronic Toll Collection )資料─各類車種通行量統計(TDCS_M03A),2019-2021年。
[參考資料]
1.資料科學家的pandas實戰手冊:掌握40個實用數據技巧https://leemeng.tw/practical-pandas-tutorial-for-aspiring-data-scientists.html

2.[Python資料科學]用Pandas分析資料— 資料的聚合
https://medium.com/seaniap/%E7%94%A8pandas%E5%88%86%E6%9E%90%E8%B3%87%E6%96%99-%E8%B3%87%E6%96%99%E7%9A%84%E8%81%9A%E5%90%88-e08f1b1504ed


以下程式範例為以2019年為例,其餘2年只差在年份與目標路段喔,大致上流程都一樣。
1. 載入資料

import pandas as pd     #載入pandas資料處理套件

from glob import glob   #載入glob回傳資料路徑套件
files = glob("C:/Users/Eric/Desktop/Python/M03A_20190205/TDCS_M03A_20190205_*.csv") #以glob函數來取得資料夾中所有開頭為TDCS_M03A_20190205_的資料

df = pd.concat([pd.read_csv(f,header=None) for f in files],ignore_index=True)  #以concat函數,並配合列表推導,將同一個資料夾內所有檔案一次載入,同時設定以資料沒有欄位名稱的方式
df.head()   #先偷看一下資料長相,如圖1

圖1
https://ithelp.ithome.com.tw/upload/images/20210820/20115774yWnn2VTIpm.jpg

2. 資料前置處理

df.columns = ["datetime", "OD", "NS", "vehicletype", "flow"]  #命名欄位名稱

df_05 = df[df["OD"] == "01F0928S"] #將目標路段(國五南向竹北-新竹)篩選出來,並儲存於另一個資料框
df_05.head()  #再偷看一下資料長相,如圖2

df_31 = df_05[df_05["vehicletype"] == 31] #將目標車種(小客車)篩選出來
df_31.head()   #再...看一次就好,如圖3

圖2
https://ithelp.ithome.com.tw/upload/images/20210820/20115774Woq3xYUxPo.jpg

圖3
https://ithelp.ithome.com.tw/upload/images/20210820/20115774DvPoO2cbxs.jpg

3. 產生x軸時間區間(由於原資料每5分鐘時間間隔區分太細,不利於視覺化呈現,以每30分鐘間隔分組取代,並把每個分組的車流量加總起來,如01:35-02:00這6筆資料,都分為20:00這組)

#原資料間隔是每5分鐘,為了簡化資料,改以30分鐘為間隔,故需要合併資料,前面的7筆(00:00-00:30)與後面的5筆(23:35-23:55)除外,中間資料均為每6個一組,如00:50-00:30組成一組,組名叫0030

num1 = [i for i in range(100,2400,100)]  #產生100、200...2300的整點時間
num2 = [i for i in range(130,2430,100)]  #產生130、230...2330的半點時間
temp = []

import math #載入要四捨五入函數的套件

#首先處理中間時間(除了前面7筆與後面5筆之外的資料),總共有46個時間,先依據是否可被2整除來依序放到列表中,藉此串起來,產生100、130、200、230...2330的資料
for i in range(0,46):
    if i % 2 == 0:
        temp.append(num1[i//2])
    else:
        temp.append(math.ceil(num2[i//2]))

temp2 = [i for i in temp for j in range(6)] #讓中間時間每個都重複6次
num3 = [30]
temp3 = [i for i in num3 for j in range(7)] #讓前面的時間重複7次
num4 = [2400]
temp4 = [i for i in num4 for j in range(5)] #讓後面的時間重複5次

time = temp3 + temp2 + temp4  #把所有時間串在一起
len(time)  #檢查時間總數是否相同,前面有7筆,中間46筆重複6次,後面有5筆,所以總計有288個

df_31_addtime = df_31  #複製原始資料,以備後續要加入新時間欄位
df_31_addtime["time"] = time   #將以30分鐘為間隔的新時間加入原表格,並命名為time欄位


df_31_addtime_group = df_31_addtime.groupby("time")  #依據"time"這個欄位將原資料群組化
df_31_addtime_group_sum = df_31_addtime_group.sum()  #依據各群組計算各欄位總和數值,並另外存在新變數中,如圖4

#因之前群組化時是依據新時間分組,故原本新時間分組已經被用掉了,故要再新增一次作為之後畫圖的x軸
temp5 = num3 + temp + num4
df_31_addtime_group_end = df_31_addtime_group_sum
df_31_addtime_group_end["time"] = temp5

圖4
https://ithelp.ithome.com.tw/upload/images/20210820/201157749MIcHHzfm5.jpg

5. 資料視覺化

import matplotlib.pyplot as plt  #載入畫圖套件

plt.style.use("ggplot")    #設定要運用叫做ggplot的主題


#畫第一條線,plt.plot(x, y, c)參數分別為x軸資料、y軸資料及折線的顏色 = 藍色
plt.plot(df_31_addtime_group_end["time"], df_31_addtime_group_end["flow"],c = "blue")

#設定y軸坐標軸範圍,調整圖的呈現
plt.ylim(400, 2500)  

# 設定圖例,參數為標籤、位置
plt.legend(labels=["2019"], loc = 2)

plt.xlabel("Time", fontweight = "bold", )    # 設定x軸標題及粗體
plt.ylabel("Flow", fontweight = "bold")      # 設定y軸標題及粗體

# 設定圖的標題、文字大小、粗體及位置
plt.title("TWN Highway traffic flow", fontsize = 15, fontweight = "bold")   

plt.savefig("2019 TWN Highway traffic flow.jpg",   # 儲存圖檔
            bbox_inches='tight',                   # 去除座標軸占用的空間
            pad_inches=0.0)                        # 去除所有白邊
plt.close()      # 關閉圖表

6. 大功告成
2019年:
https://ithelp.ithome.com.tw/upload/images/20210820/20115774Mo6fNa9kUU.jpg
簡評:可以看出大抵預估相符,但實際塞車時間較長,約從6點開始一路塞到16點左右。

2020年:
https://ithelp.ithome.com.tw/upload/images/20210820/201157745p5WpmF0Pf.jpg
簡評:2020年的預估與實際也大致相符,但約6點-11點左右車流明顯變少。

2021年:
https://ithelp.ithome.com.tw/upload/images/20210820/20115774ONNTgdtrqW.jpg
簡評:2021年的實際車流時序與2020年幾乎相同,均依循著相同的模式。

7. 結論
透過開放資料,我們可以運用Python來自己做一些簡單分析,經由最近3年時間,我們可以發現塞車時間通常會較預估的時間區間來得長,所以如果明年也想作為春節出遊的參考的話,也可以自己運用Python來當作自己的小助手喔。


尚未有邦友留言

立即登入留言