【问题标题】:gnuplot: plot multiple datasets from file only if all data is presentgnuplot:仅当所有数据都存在时才从文件中绘制多个数据集
【发布时间】:2013-09-03 12:55:46
【问题描述】:

把事情说清楚:

我的数据如下所示:

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

多列缺失值(仅在文件开头)。 现在我想绘制第 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 将忽略整行。

有人出主意吗?

【问题讨论】:

    标签: gnuplot


    【解决方案1】:

    基本上,您可以使用valid 函数来检查列是否包含有效数据。如果数据有效则返回1,否则返回0。所以一个可能的plot 命令看起来像这样:

    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 的评论改进了脚本。

    【讨论】:

    • 我不确定我是否理解 plot 命令。我从来没有见过 @ 之前它对 col_str 变量有什么作用?我也无法在帮助中找到它。你能解释一下较低的变体吗?
    • @vlad_tepesch @ 将变量视为宏,即@var 被包含在var 中的字符串替换然后求值。必须使用set macros 启用此行为。一个简单的例子是set macros; var = 'sin(x)'; plot @var。不过不知道@vareval(var)有没有区别。
    • 谢谢,我想我明白了,但是代码应该可以在宏中添加更多内容:而不是col_str = col_str . '0' col_str = col_str . '0 != col_cnt? 1/0 ' 可能是可能的,这样情节看起来像using 1:(@col_str : $4 ) 现在它应该有一个更好的名字
    • 现在我想起来了,eval@var 之间当然有区别:宏仅用于替换以构建复杂/动态命令,eval 评估给定的字符串就好像它是脚本中的一整行(有点……)。
    • @vlad_tepesch 是的,那肯定更好。如果你不介意,我会在我的回答中加入这个增强功能,因为它使它更具可读性。
    【解决方案2】:

    啊——我误解了我的输出。

    现在,如果我在上面发布的最小示例上测试整个事情,我的解决方案似乎有效。

    我现在创建了一些检查函数假人,让事情变得更好。

    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
    

    【讨论】:

    • 我喜欢你的解决方案。我不知道,一个函数的结果取决于它的参数的有效性,尽管它们没有被使用。
    • @Christoph 似乎 gnuplot 仅在所有使用的输入都有效时才评估表达式,否则它会忽略完整的数据集并且不绘制点
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-23
    • 1970-01-01
    • 2019-11-17
    • 2017-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多