这可能更容易将数据重新格式化为不同的设计。使用类似的设计
Type Fast_Result Fast_Min Fast_Max Slow_Result Slow_Min Slow_Max
会让这变得微不足道。可以使用外部程序重新格式化数据。但是,可以不进行任何重新格式化。
我们需要假设类型和方法的名称中没有空格。这允许我们使用 gnuplot 字符串变量和 word/words 函数来模拟数组。如果不满足这个假设,这将更加难以实现。
对于大多数情况,我将假设数据看起来像
POGC Fast 10.4 9.4 15.6
POGC Slow 20.3 14.2 25.5
G1 Fast 5.0 4.4 5.2
G1 Slow 11.1 6.8 13.0
如果我们使用 CSV 文件,我们可以使用 set datafile separator comma。如果第一行是标题行,我们可以使用set key autotitle columnhead 将其设置为自动跳过。其实这两条命令,剩下的命令应该没什么区别了。
假设我们有两个变量,types和methods,包含所有可能的类型和方法的值
types = "POGC G1"
methods = "Fast Slow"
我们首先将 xaxis 标签放置在每种类型的框集的中间。我们为每个组添加一个额外的框以设置组之间的空间。第一个抽动设置命令有效地“清除”所有抽动,以便我们逐个添加所需的抽动
set xtics ()
set for[i=1:words(types)] xtic add (word(types,i) (1+words(methods))/2.0+(i-1)*(words(types)+1))
现在,我们将使用set boxwidth 0.9 显式设置boxwidth。我们使用略小于 1 的值来允许每个框之间存在间隙。
接下来,我们需要几个函数。一个将在这些列表变量之一中获取索引,另一个将确定放置框的 x 坐标。
wordix(list,word) = sum[i=1:words(list)] (word(list,i) eq word)?i:0
xval(ty,me) = (wordix(types,ty)-1)*(words(methods)+1)+wordix(methods,me)
由于框样式倾向于截断框的底部,我们将使用set yrange[0:*] 明确设置我们的范围。
对于盒子,我们需要遍历每种类型,一次绘制一个,以确保它们使用与键中不同的样式。这需要我们使用条件检查来查看要绘制哪些框。在这种情况下,如果我们使用该框,我们将选择第三列,如果不使用,则选择无效值 1/0,这会导致 gnuplot 跳过该框。我们将使用矢量样式来绘制范围线。我们可以一次完成这些,因为它们的样式都相同。现在,我们可以使用 1
进行绘图
plot for[z=1:words(methods)] "data.txt" u (xval(strcol(1),strcol(2))):(strcol(2) eq word(methods,z)?$3:1/0) with boxes lt z t word(methods,z), \
"" u (xval(strcol(1),strcol(2)):4:(0):($5-$4) with vectors lc black nohead not
生产
至于设置我们的初始类型和方法变量,我们要么必须在脚本中设置它们,要么使用外部程序。我们将假设数据采用分号分隔的 csv 格式,带有标题行,并命名为 data.txt。
如果python3可用,定义一个函数(使用windows shell引用)
getcolumnvalues(x) = sprintf('python -c "data=set([x.split(\";\")[%d] for x in open(\"data.txt\",\"r\")][1:]);print(*sorted(data))"',x-1)
或者,如果 python3 不可用,但标准 unix 程序(awk、sort、uniq 和 paste)可用,我们可以将其定义为(再次使用 windows shell 引用)
getcolumnvalues(x) = sprintf('awk -F; "(NR>1) {print $%d;}" data.txt | sort | uniq | paste -s -d" "',x)
现在,我们可以像这样设置变量了
types = system(getcolumnvalues(1))
methods = system(getcolumnvalues(2))
1 我通常喜欢使用 i 作为我的迭代变量,但请注意 wordix 函数使用相同的变量进行迭代。当我们在每次迭代期间调用该函数时(通过 xval 函数),我们需要为绘图迭代使用不同的变量。这是一个很容易错过的错误(我在打字时花了大约 15 分钟试图弄清楚为什么它因此而不起作用)。在这种情况下,重要的是要记住,gnuplot 虽然有一些强大的编程结构,但没有在大多数语言中保护我们的范围规则。所有变量都是“全局的”,我们必须注意名称。