地圖/統計圖/3d 函數圖/實驗報告圖 -- Gnuplot 純畫圖
* * * 也請參考 教學短片 * * *
簡介
GNUPLOT 是一套跨平臺的數學繪圖自由軟體, 可以繪製數學函數圖形, 也可以從純文字檔讀入大量數據 (例如座標資料), 繪製統計圖表等等。 它不是統計軟體, 也不是數學軟體, 它純粹只是一套函數/資料繪圖軟體。 它只專心做一件事 - 畫圖 - 但是把這件事做得非常完整。 最重要的是, 它與其他軟體保持良好的溝通: 可以產生 png, svg, ps, hpgl, ... 等等開放的圖形檔案格式的輸出, 供文書處理/簡報/試算表/... 等等軟體匯入。 如果再學一點 regular expression, 更可以將任何有規律的文字座標檔轉換成 gnuplot 認得的簡單格式, 滿足你任何資料繪圖的需求。 這種 「組合式學習」 的設計, 在加上它歷久不衰的特性, 使它具有 長遠學習投資價值 [ 長線投資的電腦學習策略 2016 版, 含 「阿貴的繪圖工具箱」] 大力推薦給所有理工科系的同學, 及其他任何科系需要做統計繪圖的同學。
Windows 用戶, 下載 時請注意: 如果您的系統已有 cygwin 或 XLiveCD, 則下載 gp400win32x11.zip ; 一般人應該沒有 cygwin/XLiveCD, 因此應下載 gp400win32.zip。
另外, 我還幫它寫了一個 GUI 控制前端 dynagpt-0.4, 非常適合國中到大學程度的解析幾何教學, 可惜還沒有時間寫手冊。
現在就讓我們直接在命令列打 gnuplot
進入它的命令列環境。
plot x*x-4*x+3 |
# 畫一條拋物線。 注意它的對稱軸在 x=2。 |
a=-1; b=-2; c=3 |
# 設定一些變數。 |
plot a*x*x+b*x+c |
# 畫一條開口向下的拋物線。 注意它的對稱軸在 x=-1。 |
b=6; replot |
# 第三條拋物線。 它的對稱軸則是在 x=3。 |
show xzeroaxis |
# 目前的設定, 並不會顯示 x 軸。 |
set xzeroaxis |
# 那麼將這個設定打開吧。 |
replot |
# 重畫一次, 可以看到它與 x 軸有兩個交點。 |
如果你下以上畫圖的命令, 卻有錯誤訊息: use 'set term' to set
terminal type first 那麼應先設定繪圖模式。 在 X-Window 下可以設定:
set term x11
而在 MS Windows 下可以設定: set
term windows
如果怎麼試都失敗, 至少可以下: set term
dumb
拿文字模式下的字元來畫圖, 雖然有點醜, 至少可以練習.
(如果你透過 pietty 連到 Linux 主機, 就必須這樣設。)
[2022/5] 不要用 set term wxt
。 在 vnc 裡面,
如果採用這個設定, 繪圖視窗不會自動更新,
要等到改變視窗大小時才會更新。 即使在 .gnuplot-wxt 裡面設定
redraw=1 也沒用。
請自己畫畫看:
- x*x-2*x+3 與 x 軸有幾個交點?
- 畫一條與 x 軸相切的拋物線吧。
當然, 學任何一套軟體, 最先要學的就是:
- 如何離開?
exit
或quit
或直接按^D
- 如何求助? 例如想學 replot 的詳細用法, 可以下:
help replot
當然像 set 或 plot 這種複雜的指令, 進入help set
或help plot
之後, 還有子選單。
另外, 命令列的快速鍵也很值得學。 gnuplot 用的並不是真正的
readline 介面,
只提供其中少數幾個最常用功能, 但已經很方便。 詳見 help
line-editing
。
人口成長史
請先跳出 gnuplot, 再重新進來一次, 以確定所有設定還原。 (所有 set 回復到 default 值) 這份資料 popgrowth.txt 記載著美國加州與阿拉斯加州的人口成長史。
plot "popgrowth.txt" |
# 繪製加州人口成長史。 |
show style data |
# 如果你用的版本比較舊, 請下 set data style |
set style data lines |
# 設定成連線模式。 |
set grid |
# 模擬方格紙效果。 |
set title "population growth" |
# 加上標題。 |
replot |
# 重畫一遍, 好多了。 |
plot "popgrowth.txt" using 1:3 |
# 改繪製阿拉斯加州人口成長史。 |
show ytics |
# 看看 y 軸標示。 |
set ytics 100000 |
# 將 y 軸標示改設定成每 10 萬一格。 |
show ytics |
# 再看一次 y 軸標示。 (以下不再囉嗦) |
replot |
# 重畫一遍。 |
plot "popgrowth.txt" |
# 回頭看加州人口成長史... 怎麼會這樣? |
set ytics autofreq |
# 還是讓它自動設 y 軸標示吧。 |
plot "popgrowth.txt" using 1:2, |
# 同時畫兩圖 (請打在同一列) |
set logscale y; replot |
# 像這種情況, 用 logscale 畫圖最合適了 |
set output "growth.png" ; set term png ;
replot |
|
set output ; set term x11 ;
replot |
|
unset logscale |
# 改回正常 (非 logscale) 顯示 |
很多設定可以用
set
命令更改。 建議用對應的 show
命令查看一下更改前後的設定。 這裡的 set term ...
用來選取不同的輸出方式 (螢幕或圖檔? 那一種圖檔?) set output
...
則選取輸出的檔案名稱。 倒數第二列的那三句用來將圖存檔;
最後一列的那三句將輸出切回螢幕, 以免等一下所畫的圖全部都跑錯地方,
覆蓋掉先前畫好的圖檔。
又, 這個例子說明了: 如果數據資料裡面含有數量級相差極大的值 (例如藍鯨, 人, 老鼠的身長體重) 可以用 logscale 的設定來提高圖的可讀性。
立體圖形
用 splot 畫空間曲面。 可以用滑鼠抓著圖形旋轉, 詳細研究它的長相,
這比老師在黑板上畫圖要好玩而且有感覺多了! 像是這個馬鞍面:
splot x*x-y*y
再加上等高線,
正好可以上一點國中地理/地科:
reset # 清除之前所有的設定 set contour base set cntrparam levels 20 unset key unset ztics splot x*x-y*y
這裡的 reset 效果像是跳出 gnuplot 再進來, 把之前的 (絕大部分) set 設定改回內定值。
如果希望將等高線畫在曲面本來在空間中的位置上, 可以用: set
contour surface
取代 set contour base
;
如果只想從正上方看等高線, 不想看原始的曲面, 則需要補兩句:
unset surface; set view 0,0
或乾脆不准旋轉: set
view map
更多有趣的數學函數 3d 圖形請見另一篇講義: 「Gnuplot 十分鐘的 3d 曲面奇航」。
當然, 它不只可以畫 3-d 函數, 也可以畫 3-d 資料。 美國太空總署 JPL 實驗室的 Shuttle Radar Topography Mission 提供全球的地面高度資訊。 我下載北緯 23 度東經 121 度附近的資訊, 並寫了一個小程式 hgt2txt 將之轉換成 gnuplot 認得的純文字格式, 存成檔案 taiwan.txt:
./hgt2txt -s 100 > taiwan.txt
然後進入 gnuplot 畫圖:
reset splot "taiwan.txt" # 連線會比較清楚 set style data lines; replot # 比例怪怪的, 調一下... set xrange [0:60] set zrange [0:1e4]; replot set pm3d; replot # 著色。 set palette model HSV functions gray, 1, 1 replot # 換個調色盤看看 set palette model HSV functions gray>0.01?gray*0.9:0, gray>0.01?1:0, 1 replot # 海面畫白色; 陸地由紅到紫 set view map; replot # 如果改畫平面圖呢? set palette model XYZ functions gray**0.35, gray**0.5, gray**0.8 splot "taiwan.txt" lt 3 # 另外一個由黑到金的調色盤
最後一個 「黑金調色盤」 (呵呵 跟臺灣的政治無關, 請不要想太多) 來自 這份講義 (在本頁搜尋 "gold palette") 關於調色盤的使用, 也請見我的另一篇講義: 「Gnuplot 十分鐘的 3d 曲面奇航」。
注意到資料檔 taiwan.txt 的格式:
- 每列一個數字, 代表一點的 z 值。
- 先是所有 y=0 的點, 隔著一個空列後是所有 y=0 的點, 再隔一個空列 ...
- 資訊不足處, 可以填 nan, 那麼 gnuplot 就會自動留白。
如果在設定 data style lines 之後, 重畫, 圖就果亂掉了,
那就表示您的版本的 gnuplot 不支援這各功能。 沒關係,
補一句就可以解決:
set datafile missing "nan"
詳見 有關 gnuplot 處理 nan 的討論。
Regexp 與資料繪圖
如果您對資料繪圖有興趣, 這裡 還有更多例子; 不過需要學一點 regular expressions。 略過這部分, 對 gnuplot 的學習無甚影響; 但 regular expressions 真的超級有用, 不妨順便一起學。
示範集錦: 以世界地圖為例
Demo scripts for
gnuplot 有很多範例。 也可以下載整套的壓縮檔
(版本可能不同於上述網頁) demo.zip, 解壓縮後,
在該目錄下進入 gnuplot, 下指令: load "all.dem"
。
在原先下指令的終端機視窗 (而不是繪圖視窗) 按 Enter,
可以一口氣逐一檢視所有範例。
我們就拿其中的 cylindrical/spherical
coordinates 為例來多學一些資料繪圖的指令。 開另一個分頁, 用
less 檢視 world.dat 的內容; 又在 gnuplot 分頁當中 reset; plot
"world.dat"
... (待續)
匯出 svg 以製作漫畫/海報/插圖等等
向量繪圖軟體 Inkscape 可以用來製作漫畫/海報/插圖等等, 有 Linux 版, Mac 版, Windows 版, ...。 它所產生的 svg 檔, 是一種開放的 xml 格式, 且可以任意縮放而不失真。 我常拿它來為我的部落格文章畫一些插圖, 例如 反盜版文宣的正當性, 中間選民的力量, 數學不及格的公投法, ... 等等。
gnuplot 的輸出可不可以拿來給 inkscape 用呢? 這裡就是一個例子:
unset key unset border unset xtics unset ytics unset mouse bell(x) = exp(-x*x)/sqrt(2*pi) f1(x) = (x > -1 && x < 1) ? bell(x) : 0 plot [-3:3] bell(x) lt 1 with filledcurve, f1(x) lt 2 with filledcurve set output "normal.svg"; set term svg; replot set output; set term x11; replot
進 inkscape, 匯入 normal.svg, 選取圖形, 並用 Object 選單底下的 ungroup 功能將群組拆開, 就可得到常態分佈的向量圖。
數學圖形
用 gnuplot 畫數學函數, 其實比畫資料檔更簡單。
我們看過如何單純地以直角座標表示法畫圖, 像這樣: plot
sin(x)/x
; 但 gnuplot 還可以畫極座標圖:
set polar # 改以極座標畫圖 plot 1+cos(t) # 心臟線 plot sin(5*t) # 五瓣花 plot [0:6*pi] t # 阿基米德螺線 unset polar # 切換回直角座標
有些圖形嚴格說來不是函數, 因為一個 x 對到兩個或兩個以上的 y;
但又不一定能用很簡單的極座標表示。 這時可以改用最一般的 "參數式"
表示。 先用 set parametric
指定以下使用參數式,
以後就可以用 t 當做自變量。 當然用參數式畫圖時, 就必須給 plot
兩個數值, 例如 plot [-3:3] t*t, t*t*t
畫出一條有 cusp
(有尖角) 的曲線。 又如 plot sin(t),sin(t)*cos(t)
畫一條 "8" 字線。 現在請用 unset parametric
還原。
畫空間曲面時, 一樣可以用參數式; 此時用 u, v 當做自變量。 例如:
set parametric set hidden3d splot v*v, -u, v*(u*u+1)
splot 有支援用球面坐標與柱面坐標畫外部數據資料, 但並沒有直接支援球面坐標與柱面坐標畫函數。 沒關係, 參數式比這些座標更一般, 所以一樣可以畫出來, 例如 hyperboloid of one sheet 及 torus ("甜甜圈"):
set isosamples 30, 10 splot [-pi:pi] [-2:2] sqrt(1+v*v)*cos(u), sqrt(1+v*v)*sin(u), v set isosamples 50, 30 splot [-pi:pi] [-pi:pi] cos(u)*(5+cos(v)), sin(u)*(5+cos(v)), sin(v)
更多有趣的數學函數 3d 圖形請見另一篇講義: 「Gnuplot 十分鐘的 3d 曲面奇航」。
自訂函數
使用者可以自己定義函數。 例如訊號處理當中經常出現的 sinc 函數
可以這樣定義: sinc(x) = sin(x)/(x)
之後如果要畫它的立體版就比較簡單了: splot
sinc(sqrt(x*x+y*y))
可以用 show functions
及 show
variables
查詢先前定義的函數及變數。
Fitting
其實 gnuplot 不只可以繪圖, 也可以做一點數值運算。 Fitting 的功能很好用, fit 完成之後, 把成果函數和原始資料畫在一起, 可以很清楚地看到手邊的資料與心中的模型與是否吻合。
先看一個簡單的例子。 首先進入 octave 用亂數產生一些資料:
x=[-10:10]/8*pi; x=x' y=3.2*sin(0.7*x+0.4)+1.4*x-2.3+(rand(21,1)-0.5)*0.7 z = [x,y] save -text fit-ex1.txt z # 存檔
再進入 gnuplot, 用一個三次式去近似:
f(x) = a*x*x*x + b*x*x + c*x + d # 定義函數 (含待估參數) a=-1; b=1; c=10; d=0 # 設定參數的初始猜測值 fit f(x) "fit-ex1.txt" via a,b,c,d # fit plot "fit-ex1.txt", f(x) # 畫出, 對照比較
不過這題正好也可以用最小方差 (least square) 的方式來解。 回到 octave 很容易就可以驗算答案:
load "fit-ex1.txt" x = z(:,1) y = z(:,2) A = [x.*x.*x,x.*x,x,x-x+1] (A'*A)\(A'*y)
一些有用的經驗分享
- 若希望畫出的文字有上下標小字的效果, 在 X Window 下可用
set term x11 enh
, 然後用這樣的語法set xlabel '{/Symbol D}_x (m)'
即可達成。 請參考 GNUPLOT 4.0 - A Brief Manual and Tutorial 並在頁面內搜尋 Greek。 感謝 小明提供!
以下是舊的講義尚未整合進來的部分
修飾圖案: set 與 show 的常用選項
- 進入 gnuplot 後請先畫好一個圖, 例如
plot sin(x)/x
以下摘要說明中, (un)set xzeroaxis 表示你可以下set noxzeroaxis; replot
看看不要畫 x 軸的效果, 或下unset xzeroaxis; replot
看看要畫 x 軸的效果. 有些選項 (例如 arrow) 比 "要/不要" 還要複雜, 必須看手冊 (例如 help set arrow) 查看詳細的用法. - 要檢查目前的設定, 可以用 show 命令. 例如
show xzeroaxis
可以查詢在目前的設定下, x 軸會不會畫出來; 用show xrange
可以查詢目前 x 軸方向的數值範圍. - set xrange ...: 設定 x 軸方向的數值範圍. y 軸與 z 軸類似. (有些命令只對 x 與 y 有效, 有些對 z 也有效; 以下都只以 x 軸為例.)
- set title ...: 這張圖的標題.
- (un)set autoscale x: (不)要讓 gnuplot 自己推敲 x 軸方向的數值範圍 (range)
- (un)set xzeroaxis: (不)要畫 x 軸.
- (un)set border: (不)要畫外框.
- (un)set xtics ...: (不)要畫 x 軸上的刻度. 刻度之間的距離可以調整, 甚至可以不是常數; 刻度旁的文字可以自行指定. 欲單獨控制刻度旁的文字 (消除或改變列印格式) 見 help set format. 又, 如要以月份做為刻度旁的文字, 可以用 xmtics 選項.
- set function style ...: 用各種不同的方式來畫函數. 建議用 impulses 試一下, 可以畫出物理課本上常出現的圖式; 用 boxes 試一下, 可以畫出統計課本上常出現的圖式.
- set samples ...: 每一條曲線要由多少個點來近似 (取樣點數).
- (un)set grid: (不)要在背景上畫方格紙.
- (un)set key ...: (不)要在右上角顯示圖例 (因為一張圖上可以有好幾個函數) 另外 keytitle 可設定圖例的標題.
- set label ...: 到處亂寫文字.
- set arrow ...: 到處亂畫箭頭.
- (un)set logscale ...: 以對數比例顯示.
- Gnuplot 非常重要的用途之一是資料分析:
把搜集而來或其他程式所產生的數據資料拿來畫.
它需要的輸入格式非常簡單: 純文字檔; 每列代表一個點的坐標; #
開頭的當做註解忽略; 如果每列有兩個數字則代表 x 與 y 坐標;
如果每列只有一個數字則代表 y 坐標 (x 坐標自動指定為 1, 2, 3,
...). 例如我們可以建立一個數據資料檔叫做 apache.dat 然後下
plot "apache.dat"
- 與 set function style 相對應的, 有一個 set style data 可以用各種不同的方式來畫外部數據資料.
- 如果 data style 設定成 lines 或 linespoints, 則資料點之間會有線將它們連起來. 但若數據資料檔內有空列, 則空列前後的兩點之間不會有連線. 範例
- 使用者可以自行定義函數 (見 help user-defined)
- 常用設定可以放在 ~/.gnuplot 檔內, 每次進入 gnuplot 時, 會自動執行. 事實上也可以把相關的 gnuplot 命令與自行定義的函數寫在純文字檔內, 存成任何檔名, 只要用 load 命令就可以載進來.
- 連續畫好幾個圖時, 可用 pause 暫停, 讓看的人跟得上.
參考資料
- Gnuplot (Part I) (一些設定說明)
- 用自由的工具學習計算物理 (文化大學物理系鄒忠毅老師)
- 使用 gnuplot 科学作图 Gnuplot 中文教程 (88頁簡體中文詳細教學)
銘謝
本文件接受以下計畫補助:
- 教育部94學年度下學期 「離島及偏遠地區中小學在職教師遠距教學課程開辦計畫 -- 短期研習課程開辦計畫」
- 經濟部工業局 「自由軟體桌面應用支援整合服務計畫」
- 本頁最新版網址: https://frdm.cyut.edu.tw/~ckhung/b/ma/gnuplot.php; 您所看到的版本: May 23 2022 02:00:16.
- 作者: 朝陽科技大學 資訊管理系 洪朝貴
- 寶貝你我的地球, 請 減少列印, 多用背面, 丟棄時做垃圾分類。
- 本文件以 Creative Commons Attribution-ShareAlike License 或以 Free Document License 方式公開授權大眾自由複製/修改/散佈。