2018九合一開票圖表完成!spreadsheet & google apps script操作分享

宋育泰
9 min readDec 6, 2018

--

中央社2018九合一選舉做的部分圖表

這次九合一選舉開票,中央社挑戰了開票圖表(總數是55個),基本上在開票數字底定後通通都完成啦,圖表形式有一點點傳統,也有一些比較創新,在製作的過程中,我有種把網路媒體當成紙媒來做的港覺。這個連結可以看到圖表與文的搭配:

這次開票圖表我最喜歡的是下面這一套(六都得票率差地圖)。實際運用到了python爬蟲、spreadsheet、google appscript、javascript。

台南行政區得票率差地圖

這次獻醜公開spreadsheet,如果有興趣的話可以來看我用的公式,也可以打開工具>指令碼編輯器,看我寫的google app script(希望它沒有太雜亂):

由來

在選前幾個月前,主管發夢開票當天要做圖表,「好啊好啊,多做不一樣的呈現也好」。於是獻立來長這樣:

執政版圖、縣市長當選人、行政區得票、議會席次、公投結果,都可以想像啊

我們用speadsheet當成溝通的工具,要什麼圖記錄在這裡、什麼圖要發去哪裡、數據也塞在這裡。這次比較重要的著眼點是,怎麼樣重複做圖表尤其是六都行政區有158個,當天深夜在illustrator填顏色也太刺激了(眼睛不脫窗才怪)。另外是縣市長選舉結果、議會席次,都套用了22個縣市(也就是一張要填10~12個數字,重複22次,還要校對……)一定要讓程式去跑!事實也證明,當天開到凌晨兩點多,當時程式的精神一定比人還好。

設想

我第一個想到是多種圖表,要統一地方彙整數字,若可以有一張大表再篩選出各類圖表需要的數據,就更好。不然人多手雜,光打開錯誤版本的檔案就夠煩的了。後來才是想構成圖表的方式,陸續加入了google app script、HiCharts的解決方式。

也就是:數據 -> 資料庫 -> 圖表呈現

數據 -> 資料庫

縣市長選舉結果的圖大抵上來說,需要3屆縣市長參選人、得票數、得票率、照片、政黨,這些資料中選會抓來就是了,把一些不需要的欄位刪掉,整理成這樣:

歷屆縣市長得票資料

在開票當天只要填入黃色底的部分:得票率與票數即可。從這個資料又可以用公式vlookup加filter,拉出台灣執政版圖資料。

=vlookup(A3,filter(‘縣市長得票率’!A$2:G$131,’縣市長得票率’!G$2:G$131=”*”,’縣市長得票率’!B$2:B$131=”2018"),4,false)

如果你點進speadsheet看公式,可以發現我這次很常用vlookup、filter,甚至是ifs搭配,這樣子可以省下很多整理的工夫。

資料庫 -> 圖表呈現

有了數據可以開始進到Google App Script,請設計師先把地圖的svg到手,以分區填入id名稱,就可以用script設定分區的顏色。(svg用illustrator、編輯器都可以編輯)

svg裡一個path代表一個區域,事先設定id,就可以由程式判斷填色。

用程式填色方法,要不是給path添加class,例如上面這張縣市執政版圖是透過設定了三種class設定底色、外加兩種class設定縣名顏色。或者是直接幫path加上style=”fill: #366EE4",其實一樣意思。

<style>
.st500{fill:#366EE4;stroke:#FFFFFF;stroke-width:1.5} /*藍色執政*/
.st600{fill:#85D3A0;stroke:#FFFFFF;stroke-width:1.5} /*綠色執政*/
.st700{fill:#E6E9EB;stroke:#FFFFFF;stroke-width:1.5;} /*無黨執政*/
.st200{fill:#FFFFFF;} /*白色縣名*/
.st1600{fill:#6E6E6E} /*黑色縣名*/
</style>
//取得id縣市名,從篩選出對應的class
<?function st(x){for (i=0; i<data.length; i++){if (data[i][0]==x){return data[i][3];}}};?>
//以下就是個縣市的path
<path id="新北1" class="<?=st("新北市")?>" d="M686.2,67.4l-2.4-0.5l-1.6,0.1l-4.1,1.5l-3.5,0.3L670,72l-0.9,1h-1.9l-1.5-0.6l-3.4-0....."
<path id="台北1" class="<?=st("台北市")?>" d="M590.3,32.4l-0.9,1.8l-0.9,0.9l-0.3,0.5l-0.9,0.9v1.8l-1.2,0.7l-0.3,1.5l0.5,1.5l1.2,0...."
<path id="屏東1" class="<?=st("屏東縣")?>" d="M475.9,655.3l-2,0.7l-1.3,1.2l-2.2,0.9l-1.8-3.1l-2-0.5h-2.6l-0.8-1.8l-1.8-0.7l-1.5-...."

從sheet取資料、套版、下載svg的程式,整理了一下其實沒有很多行:

  1. 定位到sheet、抓資料
  2. 跑個迴圈把2018資料篩出來
  3. 指定套版taiwan2018.html這個檔案,並且套資料(誒!不是svg檔嗎?因為Google App Script的檔案格式是html,所以我把svg的xml先以html先存起來)
  4. 一個下載的功能:在google drive新建一個檔案,內容是剛才套好版的html,並且取得它下載連結,用iframe敲這個網址,chrome就會開始下載了
function county() {
sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("政黨執政版圖");
data = sheet.getRange("A2:D").getValues();
var e2018 = [];
for (i=0; i<data.length; i++){
if (data[i][1]==2018){
e2018.push([data[i][0],data[i][1],data[i][2],data[i][3]])
}
};
c2018 = HtmlService.createTemplateFromFile('taiwan2018.html');
c2018.data = e2018;
var final = c2018.evaluate().getContent();
downloadh(final,"2018.svg")
};
function download(html,filename){
var att = DriveApp.createFile(filename, html, MimeType.HTML).getDownloadUrl().replace('?e=download&gd=true','');
var htmlOutput = HtmlService
.createHtmlOutput("<iframe src='"+att+"'></iframe>");
SpreadsheetApp.getUi().showModalDialog(htmlOutput,'自動下載');
}

若是進階一點到行政區投票率差地圖的話,要運用一點計算,顏色的部分則是產出了一個從藍到白到綠的21階色碼,再套用進地圖裡囉

漸層色碼的產出方式應該有很多,我是參考這個javascript:

關於怎麼重複做22個縣市?就是寫迴圈囉,可以參考我的上一篇文章:

關於用Google App Script「套版」可以參考這篇:

由於我沒用過別的帳號進過google app scirpt,不知道大家都開得起來嗎?如果有問題請通知我,再研究研究怎麼分享出來。這一篇文章其實寫得有點簡陋,若有問題歡迎找到我討論。

至於當天晚上怎麼用python抓中選會資料,等整理好再寫一篇囉。

--

--

宋育泰
宋育泰

Written by 宋育泰

a.k.a 宋卡波,想要寫些python、spreadsheet、ga & gtm,以及一些數據清理的自學大叔。