gnuplot:仅当所有数据都存在时才从文件中绘制多个数据集

gnuplot:仅当所有数据都存在时才从文件中绘制多个数据集,gnuplot,Gnuplot,要说清楚: 我有如下数据: 0, , ,1,2 1, , ,2,3 2, 1, ,4,5 3, 1, ,4,6 4, 1,1,4,7 5, 1,2,5,8 6, 1,4,6,7 plot 'file.txt' using 1:(valid(2)+valid(4)+valid(5) == 3 ? $2 : 1/0),\ ... 缺少值的多列(仅在文件开头)。 现在我要绘制第2、3和5列 但是绘图应该从我想要绘制的所有集合都有数据的点开始 所以如果我的xrange是[0:10] 如果我绘制2

要说清楚:

我有如下数据:

0,  , ,1,2
1,  , ,2,3
2, 1, ,4,5
3, 1, ,4,6
4, 1,1,4,7
5, 1,2,5,8
6, 1,4,6,7
plot 'file.txt' using 1:(valid(2)+valid(4)+valid(5) == 3 ? $2 : 1/0),\
...
缺少值的多列(仅在文件开头)。 现在我要绘制第2、3和5列 但是绘图应该从我想要绘制的所有集合都有数据的点开始

所以如果我的xrange是[0:10] 如果我绘制2,3,5,则只能绘制4:6。 如果我画2,4,5,那么从2:6应该被画出来。 是否有可能测试某个值是否存在

我试过类似的东西

plot \
"file.txt" using 1:($2 + ($3*0) + ($5*0)) with lines, \
"file.txt" using 1:($3 + ($2*0) + ($5*0)) with lines, \
"file.txt" using 1:($5 + ($3*0) + ($2*0)) with lines, \
因为我希望如果要使用的一个元素的数据不存在,那么gnuplot将忽略整行


有人有想法吗?

啊,我误解了我的想法

现在,如果我在上面发布的最小示例上测试整个过程,我的解决方案似乎是可行的

我现在创建了一些检查函数dummys,使事情变得更好

check2(x1, x2) = 0
check3(x1, x2, x3) = 0
check4(x1, x2, x3, x4) = 0
check5(x1, x2, x3, x4, x5) = 0
check6(x1, x2, x3, x4, x5, x6) = 0
check7(x1, x2, x3, x4, x5, x6, x7) = 0
check8(x1, x2, x3, x4, x5, x6, x7, x8) = 0

plot \
"file.txt" using 1:($2 + check3($2, $3, $5)) with lines, \
"file.txt" using 1:($3 + check3($2, $3, $5)) with lines, \
"file.txt" using 1:($5 + check3($2, $3, $5)) with lines, \
然而,如果有人知道更好的方法,请分享你的知识

多谢各位

编辑: 结合Christoph在另一个答案中提出的宏,整个问题更加紧凑:

set macro
check3(x1, x2, x3) = 0
AllOrNothing = "check3($2, $3, $5)"
plot \
"file.txt" using 1:($2 + @AllOrNothing ) with lines, \
"file.txt" using 1:($3 + @AllOrNothing ) with lines, \
"file.txt" using 1:($5 + @AllOrNothing ) with lines

基本上,您可以使用
valid
函数检查列是否包含有效数据。如果数据有效,则返回
1
,否则返回
0
。因此,可能的
plot
命令如下所示:

0,  , ,1,2
1,  , ,2,3
2, 1, ,4,5
3, 1, ,4,6
4, 1,1,4,7
5, 1,2,5,8
6, 1,4,6,7
plot 'file.txt' using 1:(valid(2)+valid(4)+valid(5) == 3 ? $2 : 1/0),\
...
下面是一个变体,其中要使用的列在字符串
cols
中定义。
valid
检查是动态构造的,稍后在using语句中作为宏调用

set datafile separator ','
set style data lines
set macros

cols = "2 4 5"
col_cnt = words(cols)
col_valid = ""
do for [i in cols] {
    col_valid = col_valid . sprintf("valid(%s)+", i)
}
col_valid = col_valid . '0 != col_cnt ? 1/0'

set offsets 0,0,1,1
plot 'file.txt' using 1:(@col_valid : $2) t 'col 2',\
     '' using 1:(@col_valid : $4) t 'col 4',\
     '' using 1:(@col_valid : $5) t 'col 5'
当然,您也可以在
cols
值上包含循环。我跳过了这一部分,因此保留了一些可读性


编辑:根据@vlad_tepesch的评论改进了脚本。

我喜欢你的解决方案。我不知道,函数的结果取决于它的参数的有效性,尽管它们没有被使用。@Christoph似乎gnuplot只有在所有使用的输入都有效的情况下才计算表达式,否则它会忽略完整的数据集,不会绘制点。我不确定我是否理解plot命令。我以前从未见过@它与col_str变量有什么关系?我也无法在帮助中找到它。你能解释下一个变量吗?@vlad_tepesch@将变量视为宏,即
@var
替换为
var
中包含的字符串,然后进行计算。必须使用
set宏
启用此行为。一个简单的例子是
set宏;var=‘sin(x)’;绘图@var
。但是,我不知道
@var
eval(var)
之间是否有区别。谢谢,我想我知道了,但是code应该可以在宏中添加更多内容:而不是
col_str=col_str'0'
col\u str=col\u str'0 != 上校?1/0'
可能会使绘图看起来像是使用1:(@col_str:$4)现在它应该有一个更好的名称现在我想起来了,当然,
eval
@var
之间有区别:宏仅用于替换以生成复杂/动态命令,
eval
将给定字符串作为脚本中的一整行(排序…)进行计算。@vlad\u tepesch是的,这肯定更好。如果你不介意的话,我会把这个增强放在我的答案中,因为它使它更具可读性。