以前,在「會畫畫的烏龜」一文中已對 Gnuplot 做了簡單介紹。本文講述如何使用 Gnuplot 將一組數據以散點圖、折線圖以及直方圖的形式可視化。算法
下面這組數據是個人一篇論文中的實驗數據……爲了獲得這組數據,折騰了一個多月。第一行文本是註釋。第 1 列是 7 份數據的編號。第 2 列是數據量(點數)。第 3~5 列分別是三種數據處理算法所耗時間(秒)。segmentfault
#ID N CR-tree RR*-tree MOO R-tree a 408707 132.169812 61.785783 33.539202 b 1017746 301.820305 149.091773 85.920577 c 1320154 369.331256 178.966130 99.004964 d 1565930 497.775453 226.263013 133.925556 e 1904034 598.490553 326.580407 179.858509 f 2798395 908.095829 531.302097 297.512237 g 3209425 1041.512695 560.594926 327.782766
將上一節的數據保存到 time-consuming.dat 文件中,並在同一目錄建立 time-consuming.gnu 文件,內容以下:網絡
set xlabel "樣點數量(百萬) " set ylabel "建樹時間(秒)" file = "time-consuming.dat" plot file using 2:3 title "CR-tree", \ file using 2:4 title "RR*-tree", \ file using 2:5 title "MOO R-tree"
而後,打開終端,進入 time-consuming.gnu 文件所在目錄,執行如下命令,進入 gnuplot 命令行交互環境,並載入 time-consuming.gnu 腳本文件:svg
$ gnuplot G N U P L O T Version 5.0 patchlevel 4 (Gentoo revision r0) last modified 2016-07-21 Copyright (C) 1986-1993, 1998, 2004, 2007-2016 Thomas Williams, Colin Kelley and many others gnuplot home: http://www.gnuplot.info faq, bugs, etc: type "help FAQ" immediate help: type "help" (plot window: hit 'h') Terminal type set to 'x11' gnuplot> load "time-consuming.gnu"
而後會跳出一個窗口顯示數據繪製結果——基於 time-consuming.dat 中的數據繪製的散點圖。字體
你會發現,上面的 gnuplot 腳本中對橫軸與縱軸設置的文字標註:spa
set xlabel "樣點數量(百萬) " set ylabel "建樹時間(秒)"
在繪製結果中變成了亂碼。不要糾結此事,這是古老的 X11 窗口系統對中文支持不夠友好所致。.net
繪製散點圖的語句爲:命令行
plot file using 2:3 title "CR-tree"
其意爲:將數據文件中的第 2 列與第 3 列數據分別做爲橫軸數據與縱軸數據進行繪圖,繪製結果的圖例標註爲 CR-tree
。因爲我須要在同一幅圖中繪製三種 R 樹變體的構建時間的散點圖,因此還須要將數據文件中的第 4 列與第 5 列數據與第 2 列數據組合,繼續繪製兩組散點。gnuplot 支持在同一條 plot
命令中繪製多組數據,可是每組數據的繪製語句之間要以逗號間隔,即:code
plot file using 2:3 title "CR-tree", file using 2:4 title "RR*-tree", file using 2:5 title "MOO R-tree"
爲了清晰起見,可以使用續行符進行斷行:索引
plot file using 2:3 title "CR-tree", \ file using 2:4 title "RR*-tree", \ file using 2:5 title "MOO R-tree"
注意,上述代碼中的file
能夠是同一份數據文件名,也能夠是不一樣的數據文件名。
Gnuplot 支持多種圖形終端。在 Linux 桌面環境中,Gnuplot 默認使用的圖形終端是 X11 的窗口系統。因爲 X11 的窗口系統起源於 20 世紀 80 年代,對不一樣地區所用的文字與字體的支持極差。雖然有辦法讓 X11 窗口系統顯示中文字符,但過程有些曲折,並且如今也不必再碰觸這些已通過時的知識了。再者說,X11 圖形終端的數據繪製結果也不適合在論文中使用。
若僅僅是但願繪圖結果可以顯示中文字符,可以使用 png 終端,即讓 Gnuplot 將圖形繪製結果輸出爲 png 圖片。例如,將 time-consuming.gnu 修改成:
set terminal png set output "time-consuming.png" set xlabel "樣點數量(百萬) " set ylabel "建樹時間(秒)" file = "time-consuming.dat" plot file using 2:3 title "CR-tree", \ file using 2:4 title "RR*-tree", \ file using 2:5 title "MOO R-tree"
在終端中執行:
$ gnuplot -c time-consuming.gnu
而後在同一目錄下即可得到 time-consuming.png 圖片文件:
如今橫軸與縱軸的文本標註再也不是亂碼了,都成了方塊。這是由於 png 終端默認使用的字體未包含中文字符所致。可在 Gnuplot 腳本中設置特定的中文字體及字號。例如,將 png 終端字體設置爲 9 號微軟雅黑字體:
set terminal png font "Microsoft YaHei, 9"
所得結果爲:
可能你的系統中沒有微軟雅黑字體,可使用如下 fc-list
命令從系統中搜索其餘中文字體來用:
$ fc-list :lang=zh
如今,雖然已將 time-consuming.dat 中的數據以散點圖的形式呈現了出來,可是散點圖的圖例的位置並不理想。圖例中的散點符號與數據圖的散點符號太近了。數據圖的左側位置有大片的空白,若將圖例說明移到左側,會更好一些。
使用 set key
命令能夠對圖例進行調整。例如,將圖例放到左側:
set terminal png font "Microsoft YaHei, 9" set output "time-consuming.png" set key left set xlabel "樣點數量" set ylabel "建樹時間(秒)" file = "time-consuming.dat" plot file using 2:3 title "CR-tree", \ file using 2:4 title "RR*-tree", \ file using 2:5 title "MOO R-tree"
結果獲得:
圖例放到左側以後,將圖例文本與散點符號對調一下位置會更符合從左向右的閱讀邏輯:
set key left reverse
結果爲:
對調了圖例文本與散點符號的位置以後,讓圖例文本呈左對齊會更美觀一些:
set key left reverse Left
結果爲:
再讓圖例的各行間距更大一些:
set key left reverse Left spacing 1.2
結果爲:
在 plot
命令中使用 「with linespoints
」選項,即可將散點圖變成折線圖。例如:
set terminal png font "Microsoft YaHei, 9" set output "time-consuming.png" set key left reverse Left spacing 1.2 set xlabel "樣點數量" set ylabel "建樹時間(秒)" file = "time-consuming.dat" plot file using 2:3 with linespoint title "CR-tree", \ file using 2:4 with linespoint title "RR*-tree", \ file using 2:5 with linespoint title "MOO R-tree"
結果爲:
不管是散點圖中的點,仍是折線圖中的點,Gnuplot 默認使用的形狀可能不遂咱們之意。那麼,Gnuplot 支持提供了哪些點的形狀可選呢?
不一樣的 Gnuplot 圖形終端中的點的形狀是不一樣的。要查看某一特定終端支持哪些點類型,可使用 test
命令。例如,查看 png 終端中的點類型:
set terminal png set output "test.png" test
結果獲得:
上圖中的右側一列便爲點的形狀及其標號。在 plot
命令中,使用 pointtype 點的形狀標號
選項,Gnuplot 便會按照指定的形狀繪製點。例如:
set terminal png font "Microsoft YaHei, 9" set output "time-consuming.png" set key left reverse Left spacing 1.2 set xlabel "樣點數量" set ylabel "建樹時間(秒)" file = "time-consuming.dat" plot file using 2:3 with linespoint pointtype 3 title "CR-tree", \ file using 2:4 with linespoint pointtype 4 title "RR*-tree", \ file using 2:5 with linespoint pointtype 5 title "MOO R-tree"
結果爲:
若要控制點的大小,可在 plot
命令中使用「pointsize 點的大小
」選項。例如:
plot file using 2:3 with linespoint pointtype 3 pointsize 2 title "CR-tree", \ file using 2:4 with linespoint pointtype 4 pointsize 2 title "RR*-tree", \ file using 2:5 with linespoint pointtype 5 pointsize 2 title "MOO R-tree"
若同一幅圖內的各條折線上的點的大小相同,可以使用 set
命令統一設定,即:
set pointsize 2 plot file using 2:3 with linespoint pointtype 3 title "CR-tree", \ file using 2:4 with linespoint pointtype 4 title "RR*-tree", \ file using 2:5 with linespoint pointtype 5 title "MOO R-tree"
結果爲:
Gnuplot 的 test
命令輸出的結果中,不只給出了點的形狀集,也給出了線的類型集。例如,圖中的 dashtype
給出了 png 終端支持的虛線類型。看了以後,你會發現,png 終端並不支持虛線,僅支持用戶選擇線寬與線的顏色。
在 plot
命令中,使用「linewidth 寬度
」修改線寬。例如:
plot file using 2:3 with linespoint pointtype 3 linewidth 2 title "CR-tree", \ file using 2:4 with linespoint pointtype 4 linewidth 2 title "RR*-tree", \ file using 2:5 with linespoint pointtype 5 linewidth 3 title "MOO R-tree"
結果爲:
至於線的顏色的設定,須要在 plot
命令中使用「linecolor 顏色標號
」選項。顏色標號,從 test
命令輸出結果的右側的點的形狀集合中選擇。例如:
plot file using 2:3 with linespoint pointtype 3 linewidth 2 linecolor 2 title "CR-tree", \ file using 2:4 with linespoint pointtype 4 linewidth 2 linecolor 4 title "RR*-tree", \ file using 2:5 with linespoint pointtype 5 linewidth 3 linecolor 7 title "MOO R-tree"
結果爲:
在熟悉了 plot
命令格式「plog 數據文件名 with ... title 圖例
」中的各個選項以後,可使用它們的簡稱以簡化 plot
命令。上一節最後給出的 plot
命令,可簡化爲:
plot file u 2:3 w lp pt 3 lw 2 lc 2 t "CR-tree", \ file u 2:4 w lp pt 4 lw 2 lc 4 t "RR*-tree", \ file u 2:5 w lp pt 5 lw 3 lc 7 t "MOO R-tree"
前文中繪製的數據圖,描述的是基於三種 R 樹變體爲 7 份採樣點集構建索引結構耗費的總時間。對於每份採樣點集,如今我想統計樣點插入索引結構中的平均耗時,亦即將 time-consuming.dat 文件中的第 3~5 列數據分別處以第 2 列數據。
Gnuplot 支持數據按列運算。對於上述需求,可將 time-consuming.dat 修改成:
set terminal png font "Microsoft YaHei, 9" set output "time-consuming.png" set key left reverse Left spacing 1.2 set xlabel "樣點數量" set ylabel "樣點插入過程平均耗時(秒)" file = "time-consuming.dat" plot file u 2:($3/$2) w lp pt 3 lc 2 t "CR-tree", \ file u 2:($4/$2) w lp pt 4 lc 4 t "RR*-tree", \ file u 2:($5/$2) w lp pt 5 lc 7 t "MOO R-tree"
結果爲:
可將這種數據繪製爲直方圖(柱狀圖)。例如:
set terminal png font "Microsoft YaHei, 9" set output "time-consuming.png" set key left reverse Left spacing 1.2 set xlabel "採樣點集" set ylabel "樣點插入過程平均耗時(秒)" file = "time-consuming.dat" set style data histogram set style histogram clustered gap 2 set style fill pattern 1 border plot file u ($3/$2):xticlabels(1) t "CR-tree", \ file u ($4/$2):xticlabels(1) t "RR*-tree", \ file u ($5/$2):xticlabels(1) t "MOO R-tree"
在直方圖中,三種 R 樹變體的構建效率高下立見:
如下語句用於將數據圖形設爲直方圖風格,並設置直方圖間隔與填充模式:
set style data histogram set style histogram clustered gap 2 set style fill pattern 1
對於直方圖,用於繪製散點圖或折線圖的 plot
命令再也不適用。繪製直方圖的 plot
命令只須要一組縱軸數據,而後將橫軸用文本進行標註。在上述 plot
命令中,($3/$2):xticlabels(1)
的意思是:將數據文件中的第 3 列的數據除以第 2 列的數據,並將結果做爲縱軸數據,而後將數據文件中的第 1 列文本做爲橫軸上的標註文本。
在 Gnuplot 的 test
命令的輸出結果中,也包含着與直方圖相關的填充樣式,主要是填充圖案與顏色。使用 fillstyle
設定填充樣式。例如,將 MOOS R 樹的直方圖設置爲純色填充,將另外兩種 R 樹變體分別用圖案 1 與 2 填充:
set terminal png font "Microsoft YaHei, 9" set output "time-consuming.png" set key left reverse Left spacing 1.2 set xlabel "採樣點集" set ylabel "樣點插入過程平均耗時(秒)" file = "time-consuming.dat" set style data histogram set style histogram clustered gap 2 plot file u ($3/$2):xticlabels(1) fillstyle pattern 4 t "CR-tree", \ file u ($4/$2):xticlabels(1) fillstyle pattern 5 t "RR*-tree", \ file u ($5/$2):xticlabels(1) fillstyle solid 0.5 t "MOO R-tree"
結果爲:
pattern
選項用於設定填充圖案,Gnuplot 對不一樣圖形終端支持的填充圖案可在 Gnuplot 的 test
命令輸出結果中查看。solid
選項用於指定純色填充,其後的數字用於指定填充顏色的深淺,該數字的取值範圍爲 [0, 1],其值越大,顏色越深。
至於直方圖的顏色設置,與折線圖的顏色設置相同,皆使用 linecolor
選項,在此再也不贅述。
直方圖相關繪圖選項也有相應的簡稱,例如:
plot file u ($3/$2):xtic(1) fs p 4 t "CR-tree", \ file u ($4/$2):xtic(1) fs p 5 t "RR*-tree", \ file u ($5/$2):xtic(1) fs s 0.5 t "MOO R-tree"
上一節繪製的直方圖,圖例的位置又出現了問題,它與直方圖出現了重疊。須要再將它挪移到一個合適的位置上。採樣點集 c 的直方圖上方是比較理想的位置。這時,須要使用圖例中心的絕對定位功能將其移動到目標位置。
用於設定圖例中心絕對位置的命令爲「set key center at x, y
」,其中 x
與 y
爲繪圖區域內某個位置的座標值。如何得到採樣點集 c 的上方理想位置的座標值呢?此時,能夠藉助 Gnuplot 的 X11 終端。由於在 X11 的終端窗口中,光標(鼠標)的位置會即時的顯示於窗口的左下角。使用這種辦法,能夠很順利的肯定 (1.65, 0.000325)
是比較理想的目標位置,將其定爲圖例的中心:
set key center at 1.65, 0.000325
結果爲:
Gnuplot 可將繪製的圖形輸出爲 ConTeXt 文檔,而後使用 context
命令將 ConTeXt 文檔「編譯」爲 PDF 文檔。這樣作的好處是,PDF 文檔中的數據圖是以矢量圖的形式存在的。矢量圖的好處是,能夠隨意縮放而不失真,適合做爲論文中的插圖。png 格式的圖片,是像素圖,對圖片進行放大或縮小會致其模糊,於是只適合做爲網絡文檔中的插圖,例如本文中的全部插圖皆爲 png 格式。
要使用 Gnuplot 的 ConTeXt 終端,前提是你的系統中已經安裝 ConTeXt 環境。若未安裝,可參考「睦鄰友好的 ConTeXt Standalone」與「zhfonts:ConTeXt MkIV 中文支持的 Hacking」這兩份文檔進行安裝,而後按照 http://wiki.contextgarden.net... 的說明爲 ConTeXt 安裝 gnuplot 模塊。作好這些準備工做以後,即可實現 gnuplot 與 ConTexT 的協做。
time-consuming.gnu 的 ConTeXt 終端版本以下:
set term context standalone size 12cm,8cm header '\usemodule[zhfonts]' set output 'time-consuming.tex' set key left reverse Left spacing 1.2 set key center at 1.65, 0.000325 set xlabel "採樣點集" set ylabel "樣點插入過程平均耗時(秒)" file = "time-consuming.dat" set style data histogram set style histogram clustered gap 2 plot file u ($3/$2):xtic(1) fs p 1 t "CR-tree", \ file u ($4/$2):xtic(1) fs p 2 t "RR*-tree", \ file u ($5/$2):xtic(1) fs s 0.5 t "MOO R-tree"
在終端中執行如下命令即可生成 time-consuming.pdf:
$ gnuplot -c time-consuming.gnu $ context time-consuming
結果以下圖所示:
因爲字體尺寸以及終端環境的不一樣,原來適用於 png 終端的圖例,如今不適於 ConTeXt 終端了。更糟糕的是,如今整幅圖沒有合適的位置放置圖例。要解決這一問題,須要將縱軸的尺度增大,從而製造出足夠的空間。
使用 set yrange
能夠設置縱軸的尺度。例如:
set yrange [0.00005:0.00040]
結果以下圖所示:
如今,縱向的空加足夠安放圖例了,可是須要從新設定圖例的中心,讓圖例向上偏移一些。此外,軸的數據,目前的單位是秒,若使用毫秒爲單位,可以讓數據圖的寬度減少一些。將這方方面面考慮周全,最終讓我滿意的代碼以下:
set term context standalone size 12cm,8cm header '\usemodule[zhfonts]' set output 'time-consuming.tex' set key left reverse Left spacing 1.2 set key center at 1.4, 0.37 set xlabel "採樣點集" set ylabel "樣點插入過程平均耗時(毫秒)" set yrange [0.05:0.42] file = "time-consuming.dat" set style data histogram set style histogram clustered gap 2 plot file u (1000*$3/$2):xtic(1) fs p 1 t "CR-tree", \ file u (1000*$4/$2):xtic(1) fs p 2 t "RR*-tree", \ file u (1000*$5/$2):xtic(1) fs s 1 t "MOO R-tree"
最終獲得了個人論文中的第一幅實驗數據圖:
最終之因此採用 ConTeXt 終端生成直方圖,是爲了得到矢量圖。可能有些同窗是使用 MS Word 寫論文,認爲 Gnuplot 與 ConTeXt 所作的這一切都與 MS Word 無關。事實上並不是如此。由 ConTeXt 終端生成的 PDF 文檔,可經由 inkscape 轉換爲 svg 格式。在 Windows 平臺下,MS Visio 能夠導入 svg 圖形,而後再轉存爲 emf 格式的圖形文件,這是 MS Word 支持的矢量圖格式。對於打算投 SCI 期刊的論文,因爲許多 SCI 期刊使用 LaTeX 排版。PDF 文檔格式的圖片,可直接在 LaTeX 文檔中使用。
事實上,Gnuplot 也提供了 pdfcairo 終端,能夠直接生成 PDF 文檔格式的圖片,可是圖形的繪製結果有些粗糙。使用 ConTeXt 終端不只可以獲得比較精美的圖形,並且能夠充分利用 ConTeXt 對圖形中的文本標註進行更好的排版,並且也能夠插入數學公式。