dad*_*ada 1 plot gnuplot markers columnheader
我有一个看起来像这样的数据文件:
"curve 0"
0 0.7800
10 0.333
12 0.5136
24 0.2096
26 -0.066
40 -0.674
42 -1.123
"curve 1"
0 0.876
2 0.73
4 0.693
6 0.672
10 0.70
12 0.88
16 0.95
148 -0.75
"curve 2"
8 2.2305
10 2.144
12 2.13
76 1.26
78 0.39
98 -0.97
Run Code Online (Sandbox Code Playgroud)
我想使用gnuplot绘制每个数据块,独立于其他数据块。这是我用于此目的的代码:
plot 'file' i 0 u 1:2 w lines title columnheader(1),\
'file' i 1 u 1:2 w lines title columnheader(1),\
'file' i 2 u 1:2 w lines title columnheader(1),\
'file' i 3 u 1:2 w lines title columnheader(1)
Run Code Online (Sandbox Code Playgroud)
工作正常。
现在,我想确定每个数据块中具有最大y值的点(x,y),并用与该数据块对应的曲线具有相同颜色的标记对其进行绘制。我尝试使用
max_y = GPVAL_DATA_Y_MAX
replot 'file' u ($2 == max_y ? $2 : 1/0):1
Run Code Online (Sandbox Code Playgroud)
在前面的代码之后,但似乎在整个第二列(包括所有块)中找到了最大值。
我想做的第二件事是:对于每个数据块,并使用形状不同于最大值的标记但形状(但曲线颜色)相同的标记,绘制该块的第一行。
gnuplot和我绘制曲线的方式(columnheader)是否可以完成这两项任务?
可以做到的。它将广泛使用stats命令和一个临时文件。在gnuplot 5中,可以使用命名数据块在内存中创建临时文件(请参阅参考资料help datablocks)。
此外,由于plot命令在很大程度上是重复性的,因此可以将plot用作语法
plot for[in=0:2] 'file' i in u 1:2 w lines t columnheader(1)
Run Code Online (Sandbox Code Playgroud)
它将使用变量in中的值0到2重复plot命令(您提供的命令使用四个数据块,但您提供的数据文件只有3个)。
以下脚本将完成您想要的操作:
stats 'file' u 1:2 nooutput
blocks = STATS_blocks
set print 'tempfile'
first_y = ""
first_x = ""
do for[i=0:blocks-1] {
stats 'file' index i u (first_x=($0==1)?sprintf("%s %f",first_x,$1):first_x,first_y=($0==1)?sprintf("%s %f",first_y,$2):first_y,$1):2 nooutput
print sprintf("%f %f",STATS_pos_max_y,STATS_max_y)
}
print ""
print ""
do for[i=1:blocks] {
print sprintf("%s %s",word(first_x,i),word(first_y,i))
}
set print
plot for[i=0:blocks-1] 'file' i i u 1:2 w lines title columnheader(1),\
for[i=0:1] 'tempfile' i i u 1:2:($0+1) w points pt (i==0?7:9) lc variable not
Run Code Online (Sandbox Code Playgroud)
产生(与您提供的数据文件一起)
在曲线0和2的情况下,第一个点和最大点相同,因此符号被遮盖了。
重新进行此操作,但更改规格以将第一个点标记向上移动0.1,我们可以看到它们显示在应有的位置。
本节将很长,但是我将分解代码并尽可能地逐行详细解释它,因为这里有一些微妙的内容。
前两行
stats 'file' u 1:2 nooutput
blocks = STATS_blocks
Run Code Online (Sandbox Code Playgroud)
在文件上运行stats命令。由于指定了列标题,因此如果不指定使用规范,则stats函数将失败,因此我们为其指定了u 1:2规范。该nooutput选项告诉stats命令捕获结果,但不输出结果。在这里,我们只关心获取块数。我们将其存储在变量块中(因为以后的stats命令将覆盖该变量)。我们可以给定一个命名前缀,但是这样可以保存所有变量,因此没有理由。代替这两个命令,在正好为3个块的情况下,我们可以将值3替换为下面出现的所有块,但是这样就不会对块的数量进行硬编码。
接下来,我们set print 'tempfile'将打印命令重定向到一个临时文件。我们将建立一个新的数据文件,其中包含最高点和第一点。
下一部分代码
first_y = ""
first_x = ""
do for[i=0:blocks-1] {
stats 'file' index i u (first_x=($0==1)?sprintf("%s %f",first_x,$1):first_x,first_y=($0==1)?sprintf("%s %f",first_y,$2):first_y,$1):2 nooutput
print sprintf("%f %f",STATS_pos_max_y,STATS_max_y)
}
Run Code Online (Sandbox Code Playgroud)
是最困难的,绝大部分魔术发生的地方。我们将创建一个包含两个数据块的临时文件。第一个是最大值,第二个是第一个值。我们将计算内存中的第一个点,并在创建第一个数据块后将它们相加。x坐标和y坐标将存储在以空格分隔的字符串变量中。
我们遍历所有数据块并为其计算stats命令。表达方式
(first_x=($0==1)?sprintf("%s %f",first_x,$1):first_x,first_y=($0==1)?sprintf("%s %f",first_y,$2):first_y,$1)
Run Code Online (Sandbox Code Playgroud)
为每个读入的点重新分配两个字符串变量。为此,它首先检查该点是否是序列中的第一个点($ 0的值将为1,因为0的值对应于标题行)。如果是的话,它将通过将第一列的值添加到字符串变量中来重建字符串变量(对于y坐标也是如此)。否则,它只会将同一事物重新分配给变量。最后,它返回第一列中的值。将表达式放在括号中并以逗号分隔时,将依次评估每个表达式,并返回最终值。
因此stats命令的行为就像
stats 'file' index i u 1:2 nooutput
Run Code Online (Sandbox Code Playgroud)
但是这个小技巧使我们能够读取第一行值并在输入时存储它们。最后,将打印出最大y值的点。这将进入临时文件。
现在,我们需要将第一点添加到临时文件中作为新的数据块。因此,首先我们打印两条空白行,然后再次遍历正在运行的块数
print sprintf("%s %s",word(first_x,i),word(first_y,i))
Run Code Online (Sandbox Code Playgroud)
对于每个块(其中,i是块的编号)。word函数将字符串变量视为空格分隔的单词列表,并提取所请求的单词。此时,我们的字符串变量看起来像
0.000000 0.000000 8.000000 # first_x
0.780000 0.876000 2.230500 # first_y
Run Code Online (Sandbox Code Playgroud)
最后,我们发布set print恢复打印命令以打印到控制台的命令。现在我们已经建立了一个临时文件,看起来像
0.000000 0.780000
16.000000 0.950000
8.000000 2.230500
0.000000 0.780000
0.000000 0.876000
8.000000 2.230500
Run Code Online (Sandbox Code Playgroud)
其中第一个数据块是具有最大y值的点,第二个数据块是第一点。
最后,我们用
plot for[i=0:blocks-1] 'file' i i u 1:2 w lines title columnheader(1),\
for[i=0:1] 'tempfile' i i u 1:2:($0+1) w points pt (i==0?7:9) lc variable not
Run Code Online (Sandbox Code Playgroud)
第一部分与之前相同,只是使用了blocks变量,而不是硬编码块数。
接下来,我们用索引0和索引1绘制两次临时文件。行颜色根据行号(在这种情况下为0到2)是可变的。我们加一来强制通常从0开始的行号为1到3。这将与之前的数据块相对应。我们用点进行绘制,然后根据要绘制的数据块选择点类型。在这种情况下,它可以是实心圆(最大值)或实心三角形(第一点)。