27 March, 2006

跑步 - 長條圖 (bar graph)

我有跑步的習慣, 每次都會把跑步的秒數記錄下來, 存在一個純文字檔,使用下面的格式(沒有斷行):

3/26, 1'16"13, 1'18"44, 1'08"75, 1'09"59, (2'01),
      1'16"05, 1'16"66, 1'16"03, 1'09"55, (2'26),
      1'14"42, 1'12"97, 1'12"30, 1'09"15, (3'39),
      1'12"22, 1'10"85, 1'08"78, (3'59),
      1'05"45, 1'07"58, 1'05"95

欄位用逗號分隔,第一個欄位是日期, 之後的欄位是我的跑步秒數,1'16"13 的意思是1分16.13秒, 在括號之內的秒數是休息秒數。 我設定跑完 800 公尺或是 1200 公尺之後就會休息一圈。

有了上面的記錄之後,我想產生如下的報表:

[3, 26, Sun] 300m
        1'16"12 1'18"43 1'08"75 1'09"59 (2'01)
        1'16"04 1'16"65 1'16"03 1'09"54 (2'26)
        1'14"42 1'12"96 1'12"29 1'09"15 (3'39)
        1'12"21 1'10"84 1'08"78 (3'59)
        1'05"45 1'07"57 1'05"95
        ----------------------------
        avg is: 1'11"71 (18.0 rounds)
我目前在 中山大學 讀書,中山大學的操場是 400 公尺, 禮拜六、日我會回到台南,到離我家比較近的 台南大學 跑步, 可是台南大學的操場只有 300 公尺,所以我希望報表在日期後面註明星期幾, 如果是星期日的話要加註 300m。 報表在休息秒數後要立刻斷行,最後算出每圈平均秒數(休息秒數不算在內)。

最後我希望將數據用長條圖表示:

bar0326_2006

其中 訓練秒數用橄欖綠顏色的長條表示, 休息秒數用淡藍色的長條表示, 平均秒數用水平紅線表示。 因為分秒的顯示方式較占空間, 所以圖上的數字都改以秒為單位。

我是用 Python 程式語言來完成報表的工作。 至於畫長條圖的工作比較困難,有考慮過用 M$ excel, Matlab, Gnuplot 這些程式來繪圖, 但最後都放棄了,因為沒有一種程式可以達到我的要求。 我的要求有:

  1. 為了區別訓練秒數跟休息秒數,我需要不同的長條可以有不同的顏色。
  2. 我希望在方條圖上畫一條水平線以表示平均秒數。
  3. 我希望突顯平均秒數附近秒數的差距,比方說平均秒數是 91 秒, 而訓練秒數是 90 秒,我希望這 1 秒的差距可以看得出來。 如果依照一般正常的比例, 1/90 是不明顯的。
或許是我的要求太特殊了,沒有任何一種程式可以達到我的要求。 最後只好用我最常用的繪圖語言 pic, 以土法鋉鋼的方式,畫出我要的長條圖。 一開始不考慮 pic 的原因是,pic 的主要是用來畫方塊圖的而不擅於畫長條圖, 當然硬要畫也是可以,就是要多花一些苦功就是了。

pic 是一種繪圖語言,一開始是用來搭配 troff 這一個排版系統,pic 的作者是 Brian W. Kernighan, 這個人同時也是 C語言的爸爸,有學過程式語言的人,看了 Kernighan 寫的使用手冊後,相信定能很快的上手。 不過 pic 不能畫出有顏色的圖,不過 pic 後來有一些特異功能的版本,如 GNU 的 gpic 及 J. D. Aplevich 寫的 dpic, 可以使用顏色。 我是使用 dpic 來上顏色的, 上顏色的方法我覺得算是某種 hack 吧, 主要是利用 dpic 可以產生 PSTricks 程式碼,PSTricks 又是另一種繪圖語言,上色是輕而易舉, 可是程式語法並沒有像 pic 這麼 user friendly。 所以如果使用 dpic 的話其實可以將 pic 及 PSTricks 這兩種語言的語法混著用, 我主要是使用 pic 的語法,到了需要上色時才使用 PSTricks 的語法。 最後再用 LaTeX 編譯過後就可以看到圖形了。

建議有程式設計經驗及熟悉命令列操作的人,可以試試看 dpic, 不會讓您失望的。 我寫的 Python 程式是 run.py 而資料檔是 run3.txt。 把 run.py 中的 rec.make_graph() 反註解就可以產生讓 dpic 編譯的程式碼了。

No comments: