Gnuplot: conditional plotting ($2 == 15 ? $2 : '1/0') with lines

后端 未结 2 1017
萌比男神i
萌比男神i 2020-12-08 10:37

My data looks like this:

10:15:8:6.06000000:
10:15:2:19.03400000:
10:20:8:63.50600000:
10:20:2:24.71800000:
10:25:8:33.26200000:
10:30:8:508.23400000:
20:15:8:60.         


        
相关标签:
2条回答
  • 2020-12-08 10:52

    +1 for a great question. I (mistakenly) would have thought that what you had would work, but looking at help datafile using examples shows that I was in fact wrong. The behavior you're seeing is as documented. Thanks for teaching me something new about gnuplot today :)

    "preprocessing" is (apparently) what is needed here, but temporary files are not (as long as your version of gnuplot supports pipes). Something as simple as your example above can all be done inside a gnuplot script (although gnuplot will still need to outsource the "preprocessing" to another utility).

    Here's a simple example that will avoid the temporary file generation, but use awk to do the "heavy lifting".

    set datafile sep ':'  #split lines on ':'
    plot "<awk -F: '{if($2 == 15 && $3 == 8){print $0}}' mydata.dat" u 1:4 w lp title 'v=15, l=8'
    

    Notice the "< awk ...". Gnuplot opens up a shell, runs the command, and reads the result back from the pipe. No temporary files necessary. Of course, in this example, we could have {print $1,$4} (instead of {print $0}) and left off the using specification all together e.g.:

    plot "<awk -F: '{if($2 == 15 && $3 == 8){print $1,$4}}' mydata.dat" w lp title 'v=15, l=8'
    

    will also work. Any command on your system which writes to standard output will work.

    plot "<echo 1 2" w p  #plot the point (1,2)
    

    You can even use pipes:

    plot "<echo 1 2 | awk '{print $1,$2+4}'" w p #Plots the point (1,6)
    

    As with any programming language, remember not to run untrusted scripts:

    HOMELESS="< rm -rf ~"
    plot HOMELESS  #Uh-oh (Please don't test this!!!!!)
    

    Isn't gnuplot fun?

    0 讨论(0)
  • 2020-12-08 10:53

    ...just stumbled across this old question... Well, it's not "acceptable" that you need an external tool for such a basic task when you want to plot the filtered data connected with lines or with linespoints. There is a gnuplot-native solution. The "trick" of the workaround is to plot several data points on top of each other and only change the coordinates if a new point has been found. The code is as simple as this:

    ### conditional plot with connected lines or linespoints
    reset session
    
    # added two datapoints for testing purposes
    $Data <<EOD
    10:15:8:6.06000000:
    10:15:2:19.03400000:
    10:20:8:63.50600000:
    10:20:2:24.71800000:
    10:25:8:33.26200000:
    10:30:8:508.23400000:
    13:20:8:8.88888888:
    15:15:8:9.99999999:
    20:15:8:60.06300000:
    20:15:2:278.63100000:
    20:20:8:561.18000000:
    20:20:2:215.46600000:
    20:25:8:793.36000000:
    20:25:2:2347.52900000:
    20:30:8:5124.98700000:
    20:30:2:447.41000000:
    EOD
    
    set datafile separator ":"
    x0 = y0 = NaN
    plot $Data u ($2==15 && $3==8 ? (y0=$4,x0=$1) : x0):(y0) w lp pt 7
    
    ### end of code
    

    Result:

    Addition:

    just for completeness. Actually, set datafile missing "NaN" is solving the problem in gnuplot5.x, but since this question was from gnuplot4.6 times... and some people seem to still plot with version 4.x

    SO_Filter.dat

    # added two datapoints for testing purposes
    10:15:8:6.06000000:
    10:15:2:19.03400000:
    10:20:8:63.50600000:
    10:20:2:24.71800000:
    10:25:8:33.26200000:
    10:30:8:508.23400000:
    13:20:8:8.88888888:
    15:15:8:9.99999999:
    20:15:8:60.06300000:
    20:15:2:278.63100000:
    20:20:8:561.18000000:
    20:20:2:215.46600000:
    20:25:8:793.36000000:
    20:25:2:2347.52900000:
    20:30:8:5124.98700000:
    20:30:2:447.41000000:
    

    The code:

    ### conditional plot with connected lines or linespoints
    reset
    FILE = "SO_Filter.dat"
    set datafile separator ":"
    
    set multiplot layout 2,1  title "generated with gnuplot 4.6"
    
    # this works with gnuplot 4.x and 5.x
    x0 = y0 = NaN
    plot FILE u ($2==15 && $3==8 ? (y0=$4,x0=$1) : x0):(y0) w lp pt 7 ti "works with gnuplot >4.x and 5.x"
    
    # this works with gnuplot >5.x
    set datafile missing "NaN"
    plot FILE u ($2==15 && $3==8 ? $1 : NaN ):4 w lp pt 7 ti "works only with gnuplot >5.x"
    
    unset multiplot
    ### end of code
    

    Result in gnuplot 4.6:

    0 讨论(0)
提交回复
热议问题