Search code examples
labelgnuplot

gnuplot 6.02 labels as a function of value


A simple gnuplot to generate labels as function of a particular column is here; also, is a function that can input a value and return a string:

set datafile separator "," 
set datafile commentschar '#'
set key autotitle columnhead # use the first line as title for data
set key noenhanced

function $labellookup(x) << EOF
    temp="null"
    if(x==2000){
    temp="two"
    }
    if(x==1000){
    temp="one"
    }
    if(x==3000){
    temp="three"}
    return temp
EOF

set yrange[*:*]

$DATA << EOD

t, v1, v2
0, 10, 3000
10, 11, 1000
15, 10, 4000
30, 11, 5000
38, 20, 6000
46, 11, 8000
47, 30, 1000
48, 31, 1000
49, 30, 4000
50, 31, 6000
51, 30, 9000
52, 30, 2000
61, 21, 3000
65, 20, 3000
70, 21, 4000
75, 10, 5000

EOD

# use column 1, and column 3 is the label; values
# are (x,y)=(column1, 2)
# column 2 is ignored

plot $DATA using 1:(2):3 with labels rotate by 90 left

When the above is run, the third column is the label as shown. How can the function be used to set the labels as the defined strings, so (for example) instead of seeing "3000" we see "three" in the plot?

enter image description here


Solution

  • If you can directly calculate from your input number the index of a lookup list (as in your case), you can simply do it like the example below. If you have more arbitrary input and output you need to do it differently.

    Script: (requires gnuplot>=5.2.0)

    ### lookup with (index)numbers as input
    reset session
    
    $Lookup <<EOD
    1000   one
    2000   two
    3000   three
    4000   four
    5000   five
    6000   six
    7000   seven
    8000   eight
    9000   nine
    EOD
    
    $Data <<EOD
    10   3.0   9000
    20   2.0   7000
    30   1.0   3000
    40   3.0   1000
    50   4.0   4000
    60   7.0   5000
    70   6.0   6000
    80   5.0   8000
    90   6.0   2000
    EOD
    
    number2text(col) = word($Lookup[int(column(col)/1000)],2)
    set offset graph 0.1, graph 0.1, graph 0.1, graph 0.1
    set key noautotitle
    
    plot $Data u 1:2 w p pt 7 lc "red", \
            '' u 1:2:(number2text(3)) w labels left offset 0,0.5 rotate by 90
    ### end of script
    

    Result:

    enter image description here

    Addition:

    If you have an arbitrary string input and want an arbitrary string output you could (mis)use the sum() function as lookup-function. Check the example below where English numbers are translated into French numbers. If a string is not present in your $Lookup, ??? is returned. It's not the most efficient, but for a small number of lookup entries it's good enough.

    Maybe gnuplot 6.x with its function blocks (as you have been using) are more efficient. Although, I find providing the lookup data in a simple table (i.e. datablock $Lookup) more convenient than defining dozens of if-clauses.

    Script: (requires gnuplot>=5.2.0)

    ### lookup/dictionary with string input
    reset session
    
    $Lookup <<EOD
    one      un
    two      deux
    three    trois
    four     quatre
    five     cinq
    six      six
    seven    sept
    eight    huit
    nine     neuf
    EOD
    
    $Data <<EOD
    10   3.0   nine
    20   2.0   seven
    30   1.0   three
    40   3.0   one
    50   4.0   four
    60   7.0   five
    70   6.0   six
    80   5.0   eight
    90   6.0   thousand
    EOD
    
    translate(col) = (s='???', sum [i=1:|$Lookup|] \
                     (strcol(col) eq word($Lookup[i],1) ? s=word($Lookup[i],2) : 0, 0), s)
    set offset graph 0.1, graph 0.1, graph 0.1, graph 0.1
    set key noautotitle
    
    plot $Data u 1:2 w p pt 7 lc "red", \
            '' u 1:2:(translate(3)) w labels left offset 0,0.5 rotate by 90
    ### end of script
    

    Result:

    enter image description here