Search code examples
gnuplotspider-chart

How to make a spider plot in gnuplot?


Let's say my data is in the form:

#atom a b c
43 1.2 1.3 1.4
44 1.2 1.4 1.8
45 1.3 1.8 1.9
46 2.0 2.3 2.4
47 1.5 1.6 1.8

And I want a plot like this one http://www.r-graph-gallery.com/143-spider-chart-with-saveral-individuals/ (the one in the middle).

how can I do that?

ps. The title in here (How to Create a Spider Plot in Gnuplot?) is misleading...


Solution

  • As far as I know, there is no built-in functionality which would directly give you the linked output. Nevertheless, one could improvise with the tools that Gnuplot does provide. The strategy would be to:

    1. analyze the file and determine the number of vertices
    2. generate the "polygonial" grid in parametric mode
    3. plot the data using the filledcurves plotting style (with transparency)

    For example (the data is represented as a datablock instead of directly passing a file):

    reset session
    set terminal pngcairo enhanced font "Times,16"
    set output 'plot.png'
    
    $DATA << EOD
    #atom a b c
    43 1.2 1.3 1.4
    44 1.2 1.4 1.8
    45 1.3 1.8 1.9
    46 2.0 2.3 2.4
    47 1.5 1.6 1.8
    EOD
    
    stats $DATA nooutput
    
    N = STATS_columns
    M = STATS_records
    
    set angles degrees
    set size ratio -1
    set style fill transparent solid 0.25
    
    unset key
    unset border
    unset xtics
    unset ytics
    
    colors = "dark-red royalblue forest-green"
    
    set style line 42 lt 1 lc rgb '#333333' dt 3 lw 0.8
    
    deltaR = 0.5
    maxR = 3 + deltaR/4
    numOfStepsInR = floor((1.*maxR) / deltaR)
    
    #helper functions
    alpha(i) = 90. - i*360./M
    posX(i, r) = cos(alpha(i))*r
    posY(i, r) = sin(alpha(i))*r
    lcolor(i) = word(colors, i%words(colors) + 1)
    
    do for [i=0:M-1] {
      stats $DATA every ::i::i using (labelValue=$1) nooutput
      set label sprintf("%d", labelValue) at posX(i,maxR),posY(i,maxR) center offset char posX(i,1),char posY(i,1)
    }
    
    do for [j=1:numOfStepsInR] {
      set label sprintf("%.1f", j*deltaR) at 0,j*deltaR left offset char 0.5,0 tc rgb '#333333'
    }
    
    set parametric
    set tr [0:1]
    
    set xr [-1.1*maxR:1.1*maxR]
    set yr [-1.1*maxR:1.1*maxR]
    
    plot \
      for [i=0:M-1] \
        (cos(alpha(i))*(deltaR*(1-t)+t*maxR)),(sin(alpha(i))*(deltaR*(1-t)+t*maxR)) w l ls 42, \
      for [i=0:M-1] for [j=1:numOfStepsInR] \
        (j*deltaR*cos(alpha(i))*t + (1-t)*j*deltaR*cos(alpha(i+1))),(j*deltaR*sin(alpha(i))*t + (1-t)*j*deltaR*sin(alpha(i+1))) w l ls 42, \
      for [i=2:N] $DATA u (posX($0, column(i))):(posY($0, column(i))) w filledcurves closed fc rgb lcolor(i-2) fs border lc rgb lcolor(i-2) lw 2, \
      for [i=2:N] $DATA u (posX($0, column(i))):(posY($0, column(i))) w p ps 1.2 pt 7 lc rgb lcolor(i-2)
    

    This produces: enter image description here