2022年9月5日 星期一

TGOS 批次地址查經緯度 + umap 私房地圖範例: 清冠一號中醫診所地圖

清冠一號中醫診所地圖 [本來想重寫 TGOS 的教學文, 做這張圖時才發現 umap 已中文化, 介面改了不少, 而且有提供 cluster map 的功能, 就乾脆連 umap 教學也一起重寫。] 接續前一篇 轉碼 big5 除錯記, 已經得到整理過的清冠一號中醫診所地址檔 3.csv。 (仍舊是 utf8 編碼, 但不會讓 iconv 消化不良。) 下一步要轉成 TGOS 規定的格式。

經過很多次實驗, 發現幾件事:

  1. 地址欄如果有郵遞區號, 很多時候反而會出錯。 最好刪掉。
  2. 很多筆資料裡面的「巿」跟平常打字出現的「市」其實並不一樣: echo '巿市' | xxd 會看到前者的編碼是 e5 b7 bf 而常用的「市」則是 e5 b8 82。
  3. id 欄必須是整數, 中間跳號沒有關係, 也不需要按照順序。 但是為了等一下處理 (join 指令) 方便, 最好每一列的 id 位數相同 (例如都是四位數)。

所以做以下處理:

perl -pe 's/巿/市/g ; s/,\d+/,/' 3.csv | \
perl -ne 'printf("%d,$2\n", $1+1000) if m/^(\d+),(.*)/' > 4.csv

另外有一列 「新北新新店區」 手動更正成 「新北市新店區」, 得到 4.csv

再來是轉編碼。 我用 vim, 它會自動判斷編碼, 所以可以編輯 big5 編碼的檔案。 但是我的學生多半採用 nano 或 geany, 這兩者無法直接編輯 big5 檔。 那就略過文字編輯器, 直接從命令列產生 TGOS 格式吧:

echo 'id,Address,Response_Address,Response_X,Response_Y' > tgos-big5.csv
cut -d, -f 1,3 4.csv | iconv -f utf8 -t big5 >> tgos-big5.csv

第一句 echo 其實就只是 TGOS 範例檔的第一 (標頭) 列而已, 只有 ascii 字元, 所以沒有編碼問題。 第二句把 4.csv 裡面的「診所名稱」欄位刪掉, 接到標頭列後面。 可以用 cat tgos-big5.csv 查看結果。 雖然是一片亂碼, 但格式看來是正確的。

然後把 tgos-big5.csv 餵給 地址轉經緯度的 TGOS 服務, 經過幾十分鐘後得到 (utf8 編碼的) 成果檔, 叫它 coords.csv 好了。 編輯 coords.csv , 把標題列刪掉。 然後水平合併兩個檔, 只保留診所的名稱、地址、經度、緯度等四個欄位: join -t, 4.csv coords.csv | cut -d, -f 2,3,6,7 > umap.csv 再手動加上這樣的標題列:

name,address,lon,lat

最終得到 umap.csv。 資料準備完成! 再來就是上傳到 umap 了:

  1. [假設你已登入 umap] 建立一個新地圖。
  2. 點右上角 「啟用編輯功能」。
  3. 點右側 「改變地圖磚圖層」, 改選 OpenStreetMap, [要從哪個伺服器取得底圖? 因為台灣國網中心有映射, 比較快。]
  4. 點右側上箭頭 「匯入資料」, 上傳剛剛準備好的 umap.csv 。 [每上傳一個檔案, 就成為一個新圖層。 一張地圖可以有好幾個圖層。]
  5. 點右側 「管理圖層」、 點剛剛新建的圖層的「筆」圖示, 在 「圖層屬性」 底下的 「圖層類型」 選 「群集後」。 [當你的地圖有很多圖徵 (features), 也就是很多個點的時候, 選用 clustered map 可以把鄰近的圖徵集中成一個數字, 地圖比較不會太亂。]
  6. 點右側齒輪 「編輯地圖設定值」, 幫地圖取一個名字。
  7. 同樣在 「編輯地圖設定值」 底下, 「預設屬性」 的 「標籤鍵」 填 「name」。 [你上傳的資料, 要用哪一個欄位作為圖徵顯示的名稱? 我們希望顯示 csv 檔裡面的診所名稱欄位而不是地址或經緯度, 所以輸入 name]
  8. 同樣在 「編輯地圖設定值」 底下, 「預設互動選項」 的 「顯示標籤」 選 「當滑過時」。 [每當滑鼠滑過一個圖徵, 就顯示它的名稱。]

最終得到壯觀的 清冠一號中醫診所地圖! 恒春有點可憐啊...沒有中醫診所願意參加嗎?

更換圖磚 (tile) 來源 採用 cluster map 方式聚集鄰近的圖徵 選用 csv 檔的 name 欄位作為圖徵的名稱 設定 「每當滑鼠滑過一個圖徵, 就顯示它的名稱」

沒有留言:

張貼留言

因為垃圾留言太多,現在改為審核後才發佈,請耐心等候一兩天。