從一趟西濱公路整理 GPS 點位,找出開車的脈絡
部落格文章

從一趟西濱公路整理 GPS 點位,找出開車的脈絡

作者 Noob
11 分鐘閱讀
#程式 #開放資料 #視覺化 #統計

十五年累積的兩百萬筆 GPS 點位可以幹嘛?自從 Google Maps 提到要把時間軸資料拔掉後,我就開始把過去的資料匯出,並使用 OwnTracks 來記錄自己的移動時間軸,我也把不同來源的資料正規化成相同格式,持續保存每天的移動紀錄。

我常在南北臺灣之間移動,偶爾也會前往東部。某天從新竹前往高雄的路上,當天完全沒有行程壓力,於是決定久違走臺 61 西濱公路。走著走著,突然在想自己到底走過幾次西濱?既然點位紀錄都在,那就來整理看看這些資料吧。

資料清理

原始資料看起來很簡單,每筆紀錄至少包含時間、經度、緯度。手機在背景記錄這些點位,但畢竟不是專業測量儀器,也不是特地開起來記錄,遇到手機快沒電或什麼情況就不一樣,有些行程的座標很密集,有些則隔了一段時間才留下下一個點。所以單次旅程的結果不好看,還是要搭配前後資料判讀,大量旅程才適合從中找出有意義的趨勢。

第一輪的清理就簡單統一時間格式、時區,排序,合併重複座標(有時候多支手機或多個服務的點位會重複/交錯計算),移除明顯錯誤的位置,計算相鄰座標距離等等,來切分出所謂的「旅程」。

GPS 座標本身只有經緯度,某些服務還記錄「速度」,但通常沒有點位名稱,所以搭配 Photon 和 Nominatim 這類 Geocoding 工具從經緯度找出地名、行政區、道路資訊等等。

每一段旅程的時間可以從第一個有效點位到最後一個有效點位算出來;旅程距離則是兩兩點位間的距離累加。就這樣近六年可以找出一百多趟旅程,可以拿來比較道路、方向、出發時間、停留時間。

第一個問題:方向和城市對不起來

首先把一百多趟旅程拿出來比,發現南下旅程跟北上旅程數量差了十幾趟,東部跟西部也差了幾趟。為了逐筆檢查,我先弄了一個 HTML 頁面,把所有旅程列出來,用表格呈現日期、出發地、抵達地、旅程時間、路線資料狀態等等。列出來就找到很多 Outlier(異常值),某些行程時間短的不可思議(高雄到新竹不到兩小時?)、某些行程又太長(臺中到高雄七小時?)

細看了這幾筆行程後,發現有些中途停留的城市沒有被拆掉,例如臺北開到臺中玩個三小時,再從臺中開到高雄,這種旅程被算成「很久的臺北-高雄旅程」;有些則是莫名被拆成兩段旅程。所以重新考量了停留次數、南北方向配對等等,重新計算旅程的端點,重新合併旅程,或把很多行程拆成兩段、三段。

清完就合理多了。原本只是想看西濱,不知不覺開始整理了這些紀錄。

第二個問題:高鐵不算開車

接著再把剛剛那些時間太短的行程抓出來,很多行程可以抓出瞬時速率超過 200 km/h,很明顯就不是開車的時速 (吧?)。

不過單用瞬時速率不可靠,高鐵路廊會經過隧道,或高鐵上網路訊號不好等等,很多高鐵行程的點位紀錄其實都比較稀疏;當然也要考慮真的是開車,但點位飄掉導致突然變很快的髒資料。

最後這邊則是用 OpenStreetMap 圖資找出高鐵路廊,如果是高速移動區段而且與高鐵路廊太重疊,就先標記為高鐵紀錄,再逐筆確認。

東部行程資料

東部行程雖然較少,但還是有幾趟環島行程或去東部的行程值得看看。第一版先用經緯度範圍篩選宜蘭、花蓮、臺東,結果把南投仁愛也算進花蓮。後來把 Geocoding 資料加進來後才把這段旅程重新校正回南投。

東部行程也常遇到點位稀疏的情況,像山區、隧道、海岸線可能隔很長一段時間才留下下一個座標,光靠相鄰點位很難確認實際道路。也是搭配 OSM 的道路資料才能確認走的路線是臺 2、國 5、臺 9 、臺 11 等等。

另外東部城市太大了,行程跨度較長,旅程常會在中間停留比較久,可能步調慢了吃飯也變比較悠閒,某次高雄到臺東的旅程就被算成「高雄->獅子」與「獅子->臺東」兩段。

接著把休息站加入計算

前面整理的是道路和旅程總時間,但長途開車還有一個很實際的變數:休息站。導航提供的預計時間主要是根據道路狀況,但自己安排長途旅程還是要把預計停多少休息站的緩衝時間算進去。

所以我從 OpenStreetMap 整理服務區/休息站的位置,再把它們和每一段旅程的 GPS 點位放在一起比對。核心座標先抓休息站周圍約 0.8 公里,考慮進出口匝道、周邊道路與定位誤差,前後資料放寬到約 1.5 公里。

第一輪先找 15-45 分鐘的停留。如果休息站附近有多個座標點,就用抵達附近的第一個點到離開附近的最後一個點計算時間。這一輪算出來,只有約 30% 的旅程有停休息站,差不多三趟才停一趟,比我印象還低很多。所以我又繼續找漏掉的資料。

第一個想到的是大安休息站,我很確定前幾天走臺 61 才停過一次,重新查看當天點位後也確實有找到位置,只是整段停留大約 10 分鐘,剛好低於第一版設定的 15 分鐘。於是我把停留時間的下限調整到 10 分鐘,這筆資料就被補回來。

接著我又想到,先前走臺 61 也曾經停過另一個休息站(臺 61 很少走,所以太有記憶點了)。從整理的 HTML 頁面找到那趟旅程,再從當天的照片找到時間點,最後找到口湖休息站。不過那天點位更稀疏,整個停車期間只留下了一個清楚的座標。

為了處理這種單點資料,我又調整判定方式,以休息站內的座標為核心,往前、往後各找最多 45 分鐘的移動資料,因此整個觀察範圍最多可以到 90 分鐘。接著用前後點位的距離估算接近與離開休息站所需的時間,剩下的時間才算成停留。口湖這筆資料最後推算約 10 分鐘,也和照片時間吻合。

這輪調整完,最後找出約 67 筆停留資料,其中 64 筆停留資料落在 10-45 分鐘的範圍內。佔整體旅程的四成,至少更接近合理的數據一點了。

最後整理出我常走的行程:

行程 旅程時間中位數 休息站 建議排程
高雄<-->雙北 5h15m 西螺/古坑 + 關西/湖口兩次 一般 5.5-6h、週末 6-6.5h
高雄<-->新竹 4h30m 西螺、古坑、清水擇一 晚間 3.5-4h、日間 4.5-5.5h
雙北<-->臺中 3h33m 關西/清水 3.5-4h
新竹<-->宜蘭 3h41m 蘇澳 約 4h

出發時間與道路選擇

出發時間也對旅程時間有很大影響,例如以新竹前往高雄來說,16:00~20:00 出發的旅程時間中位數約 4h45m,20:00~24:00 出發的旅程時間中位數約 2h55m,差了一個多小時。

但行駛國 1、國 3、和臺 61 反而找不出顯著的差異(當然也跟樣本數有關,畢竟沒事不會繞去西濱)。裡面甚至有「國 1->國 3->國 1->國 3」和「國 3->國 1->國 3->國 1」的紀錄(但換三次是啥邏輯?新竹系統/彰化系統,南部要在哪裡換?臺南嗎 XD),但多次切換可能是因為道路本身就壅塞或道路施工的情境,也不算太有代表性。

所以對我自己的行程來說,相同道路在不同時間出發,旅程時間可能差很多;但不同道路在相近時段出發,結果好像比較接近。

結語

看起來很無聊的 GPS 點位,經過一個夠具體的命題、幾輪資料清理與持續驗證,就能整理出很有趣的結果。座標本身只有時間、經緯度和少量裝置資訊;加入旅程切分、Geocoding、道路比對、速度檢查、停留判定,就開始能看出路線選擇、出發時間、停留習慣與長期變化。

這次最花時間的部分是決定每筆資料到底代表什麼。這個城市是經過還是停留?這段高速移動是高鐵、GPS 飄移,還是不同來源交錯產生的髒資料?這兩段紀錄算同一段旅程還是該拆開計算?每次修改規則,就要重新執行、抽查結果,再找出下一個 Outlier。

我後來也試著把大學時期的通勤紀錄放進類似分析(畢竟開頭說十五年,前面只用了六年),因為都是同一個城市內高度重複移動,很適合觀察策略如何逐漸穩定(想起大學老師說這就是 Operations Research 的有趣之處啊!)大三前後,通勤時間中位數從約 75 分鐘降至 60 分鐘,後面幾年更收斂到 56 分鐘。即使距離中位數增加約 5 公里,總時間卻縮短 15 分鐘,代表更長但更穩定的路線更容易控制每天的通勤時間。

這次會做這個分析其實也是因為 Codex 的使用額度快要重置了,我就拿來消耗點 token。但 AI 雖然可以協助撰寫 parser、批次計算距離、反查地名、分類道路、找出異常資料,真正影響成本和結果品質的地方還是一開始怎麼定義問題,以及自己是否清楚資料的限制。命題越明確,資料清理的方向就越集中,也能減少錯誤查詢、重複運算、無效模型使用成本。

而常開車的人通常已經有自己的駕駛方式,每個人的用車習慣與休息需求不同、目的地和出發時間也各自不同。這份分析是我個人的旅程資料,用實際走過的旅程檢查印象、修正規則,再把新的紀錄加入統計。

也許有緣再整理看看其它走過的公路。

發佈於 August 1, 2026
Noob
熱愛技術、程式設計,喜歡分享知識與經驗。

留言

Loading...

Webmention

尚無互動