[原创] gnuplot调教记

转载请注明出处:http://www.codelast.com/

gnuplot是命令行绘图的极佳选择之一。用它画出一副简单的图极其容易,但是对画出的图进行微调却很令人抓狂,这主要“得益”于gnuplot超级强大的功能,以及无穷无尽纷繁复杂的说明文档,通常让人没时间去细细研究。如果你经常有gnuplot的使用需求,那么可以仔细研读一下它的文档,否则,还是像我一样,现学现用吧。我折腾了一天多时间,把我想要的一副图给画出来了,里面涉及到了很多图像的微调过程,有些解决方案很难搜到,但我运气稍好,终究还是弄出来了,在此,作为一个使用案例来分析一下。因此,本文并不是gnuplot的使用教程,而是用gnuplot绘图时,对某些奇怪问题的解决办法的分享。

本文基于gnuplot版本:4.4,系统:RHEL 5.3『1』基本需求先说一下我要画图的基本需求。听上去很简单:就是二维平面上的X,Y坐标点线图。我有一个数据文件data.txt,第一列是日期,第二列是该日期下的数值,例如:

201410201525201410191429201410181321201410171780201410161655

下面来看看怎么把它画成图。

『2』编写最简单的shell脚本在shell脚本中调用gnuplot,绘制出一个最简单的图:

#!/bin/bashgnuplot << EOF  set terminal png  set xdata time  set timefmt "%Y%m%d"  set output "output.png"  plot "data.txt" using 1:2    quitEOF

画出的图是这样的:

文章来源:http://www.codelast.com/显然这个图非常难看,并且图上的某些内容让人匪夷所思,我们先不管它,先看看它是怎么运作的。在shell脚本中两个 EOF 中间的是gnuplot的绘图参数设置命令,每一条命令的含义分别是:set terminal png:将输出图片设置为png格式。set xdata time:设置X轴为时间。set timefmt "%Y%m%d":设置输入数据的时间格式。set output "output.png":设置输出图片的文件名,这里你可以使用绝对路径,此处为了简单,只使用相对路径,将输出到当前目录下。plot "data.txt" using 1:2:将 data.txt 作为输入数据文件,使用其第一列作为X轴,第2列作为Y轴。文章来源:http://www.codelast.com/可见要画出一幅图是相当简单的,但是正如前面所说,要调整这幅图到你满意的程度,并不是一件简单的事情——如果不调整,上面的乱糟糟图根本就没法看嘛!

『3』漫长的参数调整过程(1)去掉右上角的文字说明右上角有一个 "data.txt" using 1:2 的说明,要去掉它,需要添加一句:

set nokey

画出的图变成了:

文章来源:http://www.codelast.com/现在干净一点了。

(2)更改X轴的日期显示格式将X轴的日期改为“月-日”(例如“10-16”),加一句代码即可:

set format x "%m-%d"

画出的图变成了:

文章来源:http://www.codelast.com/X轴日期显示格式已改,没有悬念。有人说,但是它怎么有重复的日期啊?这个问题后面再说。

(3)清除Y轴显示的数值添加代码:

set format y ""

画出的图变成了:

文章来源:http://www.codelast.com/现在Y轴没数字了。

(4)添加网格图中的任意两个点,它们的Y坐标值是否相同?如果这两个点离得稍微远一点,就看不清楚了,因此,为图像添加上网格,可以很好地辅助我们识别它们是否在同一水平线上:

set grid

画出的图变成了:

文章来源:http://www.codelast.com/(5)去除X轴上重复的日期添加如下代码:

set xtics 60*60*24

画出的图变成了:

文章来源:http://www.codelast.com/这句代码为什么能“神奇”地修复X轴坐标重复的问题?如果你有耐心,可以看看这篇文章的解释。它的大概原理是:当X轴显示的值是时间的时候,xtics 的增量单位是秒,如果你要它的增量单位是天,就需要将 xtics 设置为一天的秒数,即60*60*24。

(6)设置输入的数据文件的分隔符前面我们输入的数据文件data.txt以\t为两列的数据分隔符,但如果我有自定义的分隔符,是否要先把它转成\t,然后才能给gnuplot使用呢?不需要,只要用命令指定分隔符就可以了:

set datafile separator "\t"

(7)点与点之间连线上面的图,画出的点实在太小了,如果相邻两点之间能用直线相连,看起来就清楚得多了:

plot "data.txt" using 1:2 with linespoints

画出的图变成了:

文章来源:http://www.codelast.com/这是怎么做到的呢?plot 命令中的 withlinespoints 指定了画出的图是点线图。

(8)修改一下线的颜色,线的粗细,点的大小代码:

plot "data.txt" using 1:2 with linespoints linecolor 3 linewidth 1 pointtype 5 pointsize 1 

画出的图变成了:

文章来源:http://www.codelast.com/这下就好看多了,在上面的代码中,linecolor指定了线的颜色,linewidth指定了线的宽度,pointtype指定了点的类型,pointsize指定了点的大小,可以参考gnuplot的官方文档获知诸如pointtype之类的代号分别代表什么样的点/线。

(9)在点的旁边显示其纵坐标值前面我们已经把Y轴刻度去掉了,因此有必要在点的旁边显示其纵坐标值:

plot "data.txt" using 1:2 with linespoints linecolor 3 linewidth 1 pointtype 5 pointsize 1, "" using 1:2:2 with labels

画出的图变成了:

文章来源:http://www.codelast.com/这一步的代码,比之前的代码多了 "" using 1:2:2 with labels 这部分。其中,with labels 表示在点旁边画上标签(label),但是这个label的值是什么呢?这里使用 using 1:2:2 表示第一列为X坐标值,第二列为Y坐标值,同时第二列也作为label的值。如果数据文件data.txt中有第三列,你可以用 using 1:2:3 来使用第三列作为label的值。有人说,上面还有一个空的双引号,是作什么用的呢?Sorry,这个真不记得了…

(10)不要让label和数据点交错在一起上面的数据点被label的数值盖住了,看起来很不爽,我们把数值偏移一定的位置,让它们错开:

plot "data.txt" using 1:2 with linespoints linecolor 3 linewidth 1 pointtype 5 pointsize 1, "" using 1:2:2 with labels center offset 0,0.5

文章来源:http://www.codelast.com/这下漂亮多了!起这个作用的代码是center offset 0,0.5。其中,center 加不加我没发现有什么区别;offset 0,0.5 表示把label在X轴方向平称0,在Y轴方向平移0.5。注意,平移的单位既不是像素,也不是和Y轴一样的单位,而是“相对距离”,不信我们可以把 offset 0,0.5 改成 offset -1,1,会看到label向左、向上都平移了一个单位,也就是下面这个样子:

文章来源:http://www.codelast.com/可见label平移的距离远不止一个像素点,并且向上平移的距离也不是Y轴的“1”。这个把label和数据点错开的方法,代码极其简单,但是为了找到这个solution,我搜遍了网页,试了无数种方法,其他的都有各种各样的显示问题,就是这样写才最好,找得我要吐血。

(11)为X轴添加上说明文字添加代码:

set xlabel "Date" textcolor lt 1

画出的图变成了:

文章来源:http://www.codelast.com/其中,textcolor lt 1 指定了文字的颜色。

(12)把X轴的说明文字改成中文简单地把上面的“Date”改为中文的“日期”,看看画出的图会变成什么:

文章来源:http://www.codelast.com/不出所料,中文乱码了。解决这个问题没有那么容易,虽然解决方案有千千万,不过我认为最实用的方法就是:在系统中安装支持中文的字体,并且在使用gnuplot绘图时指定使用这个字体:

set term png font "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc,12"

这句话的前半部分含义与set terminal png 相同,后半部分指定了使用的字体的路径以及文字的大小。wqy-microhei.ttc 即为文泉驿微米黑字体文件,可以从很多地方下载到,当然你也可以尝试使用其他的字体。字体文件不一定要放在/usr/share/fonts/truetype/wqy/ 路径下,但是最好遵循Linux系统中其他字体的规则。这样,画出的图就变成了:文章来源:http://www.codelast.com/(13)为图片添加标题(title)在上面已经搞定中文输出的基础上,我们再添加中文的title就很容易了:

set title "每天售出的商品数量" textcolor lt 1

画出的图变成了:

文章来源:http://www.codelast.com/(14)图片两边太挤了,空出一定的空隙添加代码:

set offset graph 0.10, 0.10

画出的图变成了:

文章来源:http://www.codelast.com/上面的代码使得我们最左、最右的两个点不会碰到坐标轴,看上去舒服多了。至于它的具体含义,我不记得了,总之可以通过调整offset的数值来观察效果。

『4』总结经过上面的一系列调整,我们终于得到了一幅看上去比较顺眼的图片。最后把完整的代码贴上来:

#!/bin/bashgnuplot << EOF  set term png font "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc,12"  set nokey  set xdata time  set timefmt "%Y%m%d"  set format x "%m-%d"  set format y ""  set offset graph 0.10, 0.10  set xtics 60*60*24  set grid  set title "每天售出的商品数量" textcolor lt 1  set xlabel "日期" textcolor lt 1  set output "output.png"  set datafile separator "\t"  plot "data.txt" using 1:2 with linespoints linecolor 3 linewidth 1 pointtype 5 pointsize 1, "" using 1:2:2 with labels center offset 0,0.5    quitEOF
[原创] gnuplot调教记

相关文章:

你感兴趣的文章:

标签云: