gnuplot

How to plot multiple colors according to column value and display a legend?


I have the following sample data in a file ("gnuplot_data"):

117 183 C3_V1
74  164 C3_V2
162 53  C3_V3

I want to make a scatter plot where the first 2 columns are X,Y coordinates and the value in column 3 is used to apply a specific color to all points matching that value. I also want to include a legend (not a color palette) that shows which values map to which color of point, e.g. a red square for C3_V1, blue for C3_V2, and green for C3_V3. I would also prefer to not use external programs such as awk. Is it possible to do this entirely within gnuplot? Based on my searching I've come up with the following:

set linetype 1 linecolor 'green' pt 5
set linetype 2 linecolor 'red' pt 5
set linetype 3 linecolor 'blue' pt 5
set linetype 4 linecolor 'black' pt 5
set key right top
set xrange [0:200]
set yrange [0:200]
plot "gnuplot_data.txt" using 1:2:(stringcolumn(3) eq "C3_V1" ? 1 : stringcolumn(3) eq "C3_V2" ? 2 : stringcolumn(3) eq "C3_V3" ? 3 : 4) with points lc variable notitle
pause -1

The plot does what I want except there is no legend despite the set key right top command:

points are color-coded but no legend

Why is the legend not displaying? Do I need to take a fundamentally different approach to create this plot?


Solution

  • If you are plotting one dataset (although with variable colors) you will get one legend entry (keyentry). However, as I understand you want as many keyentries as you have different datapoint types/colors. I assume that you don't want to change your original datafiles by adding an extra color column.

    My suggestion would be:

    Depending on your data and requirements you could maybe even simplify the following script.

    Script:

    ### plot with variable color and keyentries for each color
    reset session
    
    $Data <<EOD
    117  183  C3_V1
     74  164  C3_V2
    162   53  C3_V3
    100  100  ???
    EOD
    
    $Colors <<EOD
    C3_V1   0xff0000
    C3_V2   0x0000ff
    C3_V3   0x00ff00
    other   0xcccccc   # last entry is default color and legend entry
    EOD
    
    set xrange [0:200]
    set yrange [0:200]
    set key right top noautotitle
    
    color(i)         = int(word($Colors[i],2))
    type(i)          = word($Colors[i],1)
    lookupColor(col) = (c=color(|$Colors|), sum[i=1:|$Colors|] \
                       (type(i) eq strcol(col) ? c=color(i) : 0), c)
    
    plot $Data u 1:2:(lookupColor(3)) w p pt 5 ps 2 lc rgb var, \
         for [i=1:|$Colors|] keyentry w p pt 5 ps 2 lc rgb color(i) ti type(i) noenhanced
    ### end of script
    

    Result:

    enter image description here

    If the categories/types appear only once in your data and if you are willing to add a color column you can get the same result with the following script:

    Script 2: (output graph same as above)

    ### plot with variable color and keyentries for each color
    reset session
    
    $Data <<EOD
    117  183  C3_V1  0xff0000
     74  164  C3_V2  0x0000ff
    162   53  C3_V3  0x00ff00
    100  100  other  0xcccccc
    EOD
    
    set xrange [0:200]
    set yrange [0:200]
    set key right top noautotitle
    
    stats $Data u (rows=column(0)) nooutput  # get max. row index
    
    plot $Data u 1:2:4 w p pt 5 ps 2 lc rgb var, \
         for [r=0:rows] $Data every ::r::r u 1:(t=strcol(3),NaN):4 w p pt 5 ps 2 lc rgb var ti t noenhanced
    ### end of script