Search code examples
gnuplot

How to make Gnuplot use predefined colors for each bar (color not from data file)


Based on this https://stackoverflow.com/a/63699595/1140754 I defined an auxiliary myLinecolor(i) = word(LINECOLORS,i) to use different collors for each bar, which corresponds to the value of a row in the input data file.

Yet, which argument should I pass to myLinecolor() regarding the bar index (i.e. row in data file) being painted?

Passing myLinecolor(variable) gives error internal error : non-INTGR argument

LINECOLORS = 'red green blue yellow brown gray turquoise'
myLinecolor(i) = word(LINECOLORS,i)
set output 'results.svg'

# using xval:ydata:box_width:color_index:xtic_labels
#       0:5:(0.8):0:xtic(1)
# xval        0- each row
# ydata       5 - value of column 5
# box_width   0.8
# color_index 0 - same as the number of the row
# xtic_labels xtic(1) - value of column 1

plot 'results.csv' every ::1 using 0:5:(0.8):0:xtic(1) with boxes lc rgb myLinecolor(variable)

e.g. I would like bar1=red, bar2=green, ..., bar7=turquoise


Solution

  • Here is an example with a bar chart where every bar has a different color as defined in a string with color hex-codes. You could also use an array.

    Script:

    ### bar chart with colors defined in string
    reset session
    
    $Data <<EOD
    A    1.1
    B    6.2
    C    4.3
    D    2.4
    E    3.5
    F    7.6
    G    5.7
    EOD
    
    set yrange[0:]
    set style fill solid 1.0
    set boxwidth 0.8
    set key noautotitle
    
    # colors      red      green    blue     yellow   brown    grey     turquoise
    myColors   = "0xff0000 0x00ff00 0x0000ff 0xffff00 0xa52a2a 0xcccccc 0x30e0d0"
    myColor(i) = int(word(myColors,int(i+1)))
    plot $Data u 0:2:(myColor($0)):xtic(1) w boxes lc rgb var
    ### end of script
    

    With an array it would look like this. It's shorter, but you have to specify the size of the array, whereas with a string you can simply add more colors. Replace the last block with this:

    # colors             red       green     blue      yellow    brown     grey      turquoise
    array myColors[7] = [0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xa52a2a, 0xcccccc, 0x30e0d0]
    plot $Data u 0:2:(myColors[int($0+1)]):xtic(1) w boxes lc rgb var
    

    You can also define your linecolors via linestyle or linetype and an index, check help linestyle and help linetype. You would get a similar result if you replace the last block with

    set linetype 1 lc "red"
    set linetype 2 lc "green"
    set linetype 3 lc "blue"
    set linetype 4 lc "yellow"
    set linetype 5 lc "brown"
    set linetype 6 lc "grey"
    set linetype 7 lc "turquoise"
    plot for [i=1:7] $Data every ::i-1::i-1 u (i):2:xtic(1) w boxes lt i
    

    however, I would prefer the first variant, or maybe if at some point I will switch to gnuplot>=5.5, the following variant:

    # for gnuplot>=5.5.0
    myColors   = "red green blue yellow brown grey turquoise"
    myColor(i) = rgbcolor(word(myColors,int(column(i)+1)))
    plot $Data u 0:2:(myColor(0)):xtic(1) w boxes lc rgb var
    

    Result:

    enter image description here