Plot 单个文件和单个绘图中的多个数据块+;每个区块的标记

Plot 单个文件和单个绘图中的多个数据块+;每个区块的标记,plot,gnuplot,markers,columnheader,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 我想使用gnuplot独立地绘制

我有一个如下所示的数据文件:

"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
我想使用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)
它很好用

现在,我想在每个数据块中确定具有最大y值的点(x,y),并使用与该数据块对应的曲线具有相同颜色的标记对其进行绘制。我试着用

max_y = GPVAL_DATA_Y_MAX
replot 'file' u ($2 == max_y ? $2 : 1/0):1
在前面的代码之后,但似乎在整个第二列(包括所有块)上找到了最大值

我想做的第二件事是:对于每个数据块,使用一个形状不同但颜色(曲线颜色)与最大值标记相同的标记,绘制该块的第一条线


gnuplot和我绘制曲线的方式(columnheader)是否可以完成这两项任务

这是可以做到的。它将广泛使用stats命令和一个临时文件。在gnuplot5中,可以使用命名的数据块在内存中创建临时文件(请参见
帮助数据块

此外,由于plot命令在很大程度上是重复的,因此可以将plot用于语法

plot for[in=0:2] 'file' i in u 1:2 w lines t columnheader(1)
这将使用中变量的值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
这将生成(使用您提供的数据文件)

在曲线0和曲线2的情况下,第一个点和最大点相同,因此符号会被遮挡

对此进行补充,但修改规范,将第一个点标记向上移动0.1,我们可以看到它们显示在应该显示的位置


这一节将很长,但我将分解代码并详细解释它,尽可能逐行解释,因为这里有一些微妙的东西

前两行

stats 'file' u 1:2 nooutput
blocks = STATS_blocks
在文件上运行stats命令。由于命名的列标题,如果我们不指定using spec,stats函数将失败,因此我们为它指定
u 1:2
spec。
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) 
}
是最困难的,也是最神奇的地方。我们将创建一个临时文件,其中包含两个数据块。第一个是最大值,第二个是第一个值。我们将计算内存中的第一个点,并在创建第一个数据块后添加它们。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)
为读入的每个点重新指定两个字符串变量。为此,它首先检查该点是否是系列中的第一个点(由于0值对应于标题行,$0的值将为1)。如果是,则通过将第一列的值添加到字符串变量中来重建该字符串变量(对于y坐标也是如此)。否则,它只是将相同的内容重新分配给变量。最后,它返回第一列中的值。当表达式放在括号中并用逗号分隔时,将依次计算每个表达式,并返回最终值

因此,stats命令的行为与以前一样

stats 'file' index i u 1:2 nooutput
但是这个小技巧允许我们读取第一行的值,并在它们进入时存储它们。最后打印出y值最大的点。这将进入临时文件

现在我们需要将第一个点作为新的数据块添加到临时文件中。首先我们打印两个空行,然后我们再次迭代运行的块数

print sprintf("%s %s",word(first_x,i),word(first_y,i))
对于每个块(其中i是块的编号)。word函数将字符串变量视为以空格分隔的单词列表,并提取请求的单词。此时,我们的字符串变量如下所示

 0.000000 0.000000 8.000000 # first_x
 0.780000 0.876000 2.230500 # first_y
最后,我们发出
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
其中,第一个数据块是具有最大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
第一部分与之前相同,只是使用了blocks变量,而不是硬编码块的数量


接下来,我们用索引0和索引1绘制临时文件两次。线条颜色根据行号(在本例中为0到2)而变化。我们添加一个以强制通常基于0的行号为1到3。这将与以前的数据块相对应。我们使用点进行打印,并根据正在打印的数据块选择点类型。在这种情况下,它可以是一个填充圆(对于最大值)或填充三角形(对于第一个点)。

可以这样做。它将广泛使用stats命令和一个临时文件。在gnuplot5中,可以使用命名的数据块在内存中创建临时文件(请参见
帮助数据块

此外,由于plot命令在很大程度上是重复的,因此可以将plot用于语法

plot for[in=0:2] 'file' i in u 1:2 w lines t columnheader(1)
哪个会重复t