Setting line opacity in gnuplot without using a hex code - plot

I am using gnuplot to plot some lines and I would like to make some of these lines transparent. I know that this is possible within some terminals (e.g., aquaterm on Mac) using a command like this:
plot x lw 10 lc rgb "#77000000"
which would produce a half-transparent black line (i.e., grey) with the hex colour being black - '000000' and the alpha value being '77'. However, using this requires me to know the hex code for the colour that I want. Is it possible to specify the colour in a more standard way, for example using the colour name or number, and then to also specify the opacity level separately?
The type of command that I would be looking for would be something like:
plot x lw 10 lc rgb 'black' transparency '#77'
which does not work. Any ideas? I'm using gnuplot 5.

There is a workaround even for gnuplot 5.0. In gnuplot 5.2 you also could use arrays. Take the RGB color values from a list of defined colors and add your transparency (alpha). Of course, you have to get the color code from somewhere.
In gnuplot console type show colors and see all the 111 predefined colors in gnuplot. Basically, you could also define your own colors.
Have the gnuplot standard colors visualized here: https://stackoverflow.com/a/54659829/7295599
Code:
### add colors by name with transparency
reset session
ColorNames = "white black dark-grey red web-green web-blue dark-magenta dark-cyan dark-orange dark-yellow royalblue goldenrod dark-spring-green purple steelblue dark-red dark-chartreuse orchid aquamarine brown yellow turquoise grey0 grey10 grey20 grey30 grey40 grey50 grey60 grey70 grey grey80 grey90 grey100 light-red light-green light-blue light-magenta light-cyan light-goldenrod light-pink light-turquoise gold green dark-green spring-green forest-green sea-green blue dark-blue midnight-blue navy medium-blue skyblue cyan magenta dark-turquoise dark-pink coral light-coral orange-red salmon dark-salmon khaki dark-khaki dark-goldenrod beige olive orange violet dark-violet plum dark-plum dark-olivegreen orangered4 brown4 sienna4 orchid4 mediumpurple3 slateblue1 yellow4 sienna1 tan1 sandybrown light-salmon pink khaki1 lemonchiffon bisque honeydew slategrey seagreen antiquewhite chartreuse greenyellow gray light-gray light-grey dark-gray slategray gray0 gray10 gray20 gray30 gray40 gray50 gray60 gray70 gray80 gray90 gray100"
ColorValues = "0xffffff 0x000000 0xa0a0a0 0xff0000 0x00c000 0x0080ff 0xc000ff 0x00eeee 0xc04000 0xc8c800 0x4169e1 0xffc020 0x008040 0xc080ff 0x306080 0x8b0000 0x408000 0xff80ff 0x7fffd4 0xa52a2a 0xffff00 0x40e0d0 0x000000 0x1a1a1a 0x333333 0x4d4d4d 0x666666 0x7f7f7f 0x999999 0xb3b3b3 0xc0c0c0 0xcccccc 0xe5e5e5 0xffffff 0xf03232 0x90ee90 0xadd8e6 0xf055f0 0xe0ffff 0xeedd82 0xffb6c1 0xafeeee 0xffd700 0x00ff00 0x006400 0x00ff7f 0x228b22 0x2e8b57 0x0000ff 0x00008b 0x191970 0x000080 0x0000cd 0x87ceeb 0x00ffff 0xff00ff 0x00ced1 0xff1493 0xff7f50 0xf08080 0xff4500 0xfa8072 0xe9967a 0xf0e68c 0xbdb76b 0xb8860b 0xf5f5dc 0xa08020 0xffa500 0xee82ee 0x9400d3 0xdda0dd 0x905040 0x556b2f 0x801400 0x801414 0x804014 0x804080 0x8060c0 0x8060ff 0x808000 0xff8040 0xffa040 0xffa060 0xffa070 0xffc0c0 0xffff80 0xffffc0 0xcdb79e 0xf0fff0 0xa0b6cd 0xc1ffc1 0xcdc0b0 0x7cff40 0xa0ff20 0xbebebe 0xd3d3d3 0xd3d3d3 0xa0a0a0 0xa0b6cd 0x000000 0x1a1a1a 0x333333 0x4d4d4d 0x666666 0x7f7f7f 0x999999 0xb3b3b3 0xcccccc 0xe5e5e5 0xffffff"
myColor(c) = (idx=NaN, sum [i=1:words(ColorNames)] \
(c eq word(ColorNames,i) ? idx=i : idx), word(ColorValues,idx))
# add transparency (alpha) a=0 to 255 or 0x00 to 0xff
myTColor(c,a) = sprintf("0x%x%s",a, myColor(c)[3:])
set xrange[0:2*pi]
set samples 200
plot sin(x) w l lw 12 lc rgb myTColor("red",0xcc), \
sin(2*x) w l lw 12 lc rgb myTColor("green",0xcc), \
sin(3*x) w l lw 12 lc rgb myTColor("blue",0xcc)
### end of code
Result:
Addition:
If you even don't want long lists of color names and color hex-codes in your gnuplot script you could use the following: extract the values automatically from dummy palettes. For this, gnuplot has to plot test palette for each color. You could switch your terminal before the loop to set term unknown and after it back to your desired terminal.
I guess getting values from $PALETTE only works with gnuplot >=5.2.
Code: (Result same as above)
### add colors by name with transparency (without hex-color code list)
reset session
ColorNames = 'red green blue magenta yellow cyan' # must be existing gnuplot color names
# get the color values from dummy palettes
ColorValues = ''
RGBComp(c) = int(word($PALETTE[256],c+1)*0xff)
do for [i=1:words(ColorNames)] {
set palette defined (0 word(ColorNames,i))
test palette
RGB = sprintf("0x%02x%02x%02x",RGBComp(1),RGBComp(2),RGBComp(3))
ColorValues = ColorValues." ".RGB
}
myColor(c) = (idx=NaN, sum [i=1:words(ColorNames)] \
(c eq word(ColorNames,i) ? idx=i : idx), word(ColorValues,idx))
# add transparency (alpha) a=0 to 255 or 0x00 to 0xff
myTColor(c,a) = sprintf("0x%02x%s",a, myColor(c)[3:])
set xrange[0:2*pi]
set samples 200
plot sin(x) w l lw 12 lc rgb myTColor("red",0xcc), \
sin(2*x) w l lw 12 lc rgb myTColor("green",0xcc), \
sin(3*x) w l lw 12 lc rgb myTColor("blue",0xcc)
### end of code

Related

gnuplot - an epslatex terminal does not plot the x-label

I have this small MWE
set title font "Monospaced,13"
set grid
f(x) = 5 * log(x) / log(2)
g(x) = 5 + sqrt(5 + x)
F = '$5 \log_2(x)$'
G = '$5 + \sqrt{5 + x}$'
# set yrange [0:300]
set xrange [0:4000]
set xlabel 'My Label'
set style line 1 linecolor rgb '#a82828' linetype 1 linewidth 5 pointtype 5 pointsize 1.5
set style line 2 linecolor rgb '#516db0' linetype 1 linewidth 5 pointtype 9 pointsize 1.5
plot f(x) title F with lines ls 1, g(x) title G with lines ls 2
set terminal epslatex background rgb "grey" standalone size 10.0cm,10.0cm color colortext
set output 'RunTimeComparisonTreeIndexed.tex'
set style rect fc rgb "white" fs
set object 1 rectangle from screen 0,0 to screen 1,1 behind
set key left top box lt -1 lw 2 opaque
replot
exit
The above script relies on this TeX-post.
It gives me:
(Note that the x-label "My Label" is missing.)
What am I missing here?
Edit
I use the following LaTeX snippet for including the plot PDF file (see the linked TeX.StackExchange post):
\begin{figure}[!h]
\centering
%\setlength{\voffset}{0cm}
%\setlength{\hoffset}{0cm}
\includepdf[pages={1},pagecommand={},width=0.5\textwidth]{RunTimeComparisonTreeIndexed.pdf}
%\setlength{\voffset}{- 10cm}
%\setlength{\hoffset}{-10cm}
\label{fig:rtcti}
\caption{Hello}
\end{figure}
I'm not "fluent" in LaTeX, so this was also a good exercise for me and will be a memory aid for myself.
Use the terminal cairolatex and directly create a PDF with TeX text formatting without detour via .eps. I used MiKTeX and pdflatex under Win10. gnuplot will create two files (SO74149797.tex and SO74149797.pdf).
Script: (requires gnuplot>=5.4.2 for fillcolor for keybox)
### create pdf with TeX text formatting via cairolatex
reset session
f(x) = 5 * log(x) / log(2)
g(x) = 5 + sqrt(5 + x)
F = '$5 \log_2(x)$'
G = '$5 + \sqrt{5 + x}$'
set title font "Monospaced,13"
set xrange [0:4000]
set xlabel 'My Label'
set grid
set key left top box lt -1 lw 2 opaque fc "grey" # fillcolor option fc for gnuplot>=5.4.2
set key width 1 spacing 1.5
set style line 1 linecolor rgb '#a82828' linetype 1 linewidth 5 pointtype 5 pointsize 1.5
set style line 2 linecolor rgb '#516db0' linetype 1 linewidth 5 pointtype 9 pointsize 1.5
set terminal cairolatex pdf input size 10.0cm,10.0cm color colortext
set output 'SO74149797.tex'
plot f(x) title F with lines ls 1, \
g(x) title G with lines ls 2
set output
### end of script
LaTeX: (important to add these packages)
\documentclass[a4paper,10pt]{article}
\usepackage{graphicx}
\usepackage[cp1252]{inputenc}
\usepackage{color}
\begin{document}
\input{SO74149797}
\end{document}
Result: (screenshot from final PDF document)

How can I draw data 2D at differents points as fenceplot at Gnuplot, with a background transparent?

I have three files where each file is 2D with an x-axis vs y-axis. I plot these files as fenceplot at Gnuplot.
With this code
reset
set term postscript eps color enhanced font "Times,15"
set view 54,111
unset xrange
set xtics +.2
set ytics +.5
set yrange [0:5]
set ticslevel 0
set xlabel "Lc/Lx"
set xlabel font "" textcolor lt -.85 rotate parallel
set ylabel "R"
set ylabel font "" textcolor lt -.85 rotate parallel
set zlabel "{/Symbol D} P / P_{NS}"
set xlabel font "" textcolor lt -.85 rotate parallel
set style fill transparent solid 0.25
set pm3d depthorder
y(x) = sin(x)
set ytics ("0.40" 0, "0.45" 1, "0.50" 2)
splot "PressureDesv.dat0" u 1:(0):2 t "R=0.40", "PressureDesv.dat 1" u 1:(1):2 t "R=0.45", "PressureDesv.dat2" u 1:(2):2 t "r=0.50"
set output "maxwell_speed_distribution.eps"
replot
set output
set term x11
I obtained this plot, but I cannot fill this curves with a background tranparent.
How do I fill these curves with a background tranparency?
Assuming I understood your question correctly, check help zerrorfill and help colorspec and the following example:
Code:
### transparent zerrorfill
reset session
### create some test data
set table $Data
set xrange[0:1]
f(x,a) = a*sin(pi*x)
plot '+' u 1:(f(x,2.0)):(f(x,1.7)):(f(x,1.5)) w table
unset table
set view 55,134
set yrange[0.36:0.54]
set ytics 0.05 offset -1,0
set ztics 0.5
set xyplane relative 0
splot $Data u 1:(0.40):2:(0):2 w zerror fc rgb 0xccff0000 lc "red" ti "R=0.40", \
'' u 1:(0.45):3:(0):3 w zerror fc rgb 0xcc00ff00 lc "green" ti "R=0.45", \
'' u 1:(0.50):4:(0):4 w zerror fc rgb 0xcc0000ff lc "blue" ti "R=0.50"
### end of code
Result:
set style data zerrorfill
set style fill transparent solid 0.5 border
set xyplane at 0
set xrange [0.3 : 0.6]
set xtics (0.40, 0.45, 0.50)
splot FILE1 using (0.40):1:2:(0):2 title "File 1",\
FILE2 using (0.45):1:2:(0):2 title "File 2",\
FILE3 using (0.50):1:2:(0):2 title "File 3"
The column assignments for zerrorfill are x:y:z:zlow:zhigh

How to plot into a histogram specific values from a file using Gnuplot

I'd like to plot two bars for a histogram, one depending on the first line of a file, while the other one depending on the second line. E.g., assuming to have a CSV file like this:
1 0.5
2 0.7
I want to plot a first bar blue of value 0.5 and a second bar red of value 0.7.
I've written the following script so far (I have a multiplot because I need to plot 4 figures of equal properties):
#!/usr/bin/env gnuplot
set term pngcairo enhanced size 1500,700
set output 'accuracy_plot.png'
set multiplot layout 1,4
set xlabel 'rounds' font ',16'
set ylabel 'mean' font ',16'
set xrange[1:2]
set yrange[0:1]
set style fill solid
set grid xtics lt 0 lw 1 lc rgb "#333333"
set grid ytics lt 0 lw 1 lc rgb "#333333"
set xtics font ',14'
set xtics autofreq 1
set ytics font ',14'
set key font ',12'
set title font ',20'
###
set title 'Q1'
plot "q1.csv" using 1:2 title '' with boxes linecolor rgb 'blue', \
"truth1.csv" using 1:2 title 'truth' with lines linewidth 3 linecolor rgb 'black'
###
set title 'Q2'
plot "q2.csv" using 1:2 title '' with boxes linecolor rgb 'blue', \
"truth2.csv" using 1:2 title 'truth' with lines linewidth 3 linecolor rgb 'black'
###
set title 'Q3'
plot "q3.csv" using 1:2 title '' with boxes linecolor rgb 'blue', \
"truth3.csv" using 1:2 title 'truth' with lines linewidth 3 linecolor rgb 'black'
###
set title 'Q4'
plot "q4.csv" using 1:2 title '' with boxes linecolor rgb 'blue', \
"truth4.csv" using 1:2 title 'truth' with lines linewidth 3 linecolor rgb 'black'
###
unset multiplot
I've tried solutions like "<(sed -n '1,1p' q1.csv)" but it didn't work.
Any idea?
You don't need to post all that settings for the tics, the labels and the multiplotting to show the problem.
You can use e.g. linecolor variable to select different line types depending on the value in the first column:
set terminal png enhanced
set output 'foobar.png'
set yrange [0:1]
set style fill solid
set linetype 1 lc rgb 'blue'
set linetype 2 lc rgb 'red'
plot 'q1.csv' using 1:2:1 with boxes lc variable notitle
Note, that the changes with set linetype aren't restored with reset, but you must restart gnuplot (version 5.0 will have a reset session option for this).
I changed every CSV in this form:
R1 R2
0.5 0.7
and my script:
#!/usr/bin/env gnuplot
set term pngcairo enhanced size 1500,700
set output 'accuracy_plot.png'
set multiplot layout 1,4
set xlabel 'rounds' font ',16'
set ylabel 'mean' font ',16'
set xrange[1:2]
set yrange[0:1.5]
set style fill solid
set grid xtics lt 0 lw 1 lc rgb "#333333"
set grid ytics lt 0 lw 1 lc rgb "#333333"
set xtics font ',14'
set xtics autofreq 1
set ytics font ',14'
set key font ',12'
set title font ',20'
set style data histograms
set style histogram columnstacked
###
set title 'Q1'
plot "q1.csv" using 1 lt 1 title columnhead, \
newhistogram lt 1 at 1, '' u 1 ti col, \
newhistogram lt 2 at 2, '' u 2 ti col, \
"truth1.csv" using 1:2 title 'truth' with lines linewidth 3 linecolor rgb 'black'
###
set title 'Q2'
plot "q2.csv" using 1 lt 1 title columnhead, \
newhistogram lt 1 at 1, '' u 1 ti col, \
newhistogram lt 2 at 2, '' u 2 ti col, \
"truth1.csv" using 1:2 title 'truth' with lines linewidth 3 linecolor rgb 'black'
###
set title 'Q3'
plot "q3.csv" using 1 lt 1 title columnhead, \
newhistogram lt 1 at 1, '' u 1 ti col, \
newhistogram lt 2 at 2, '' u 2 ti col, \
"truth1.csv" using 1:2 title 'truth' with lines linewidth 3 linecolor rgb 'black'
###
set title 'Q4'
plot "q4.csv" using 1 lt 1 title columnhead, \
newhistogram lt 1 at 1, '' u 1 ti col, \
newhistogram lt 2 at 2, '' u 2 ti col, \
"truth1.csv" using 1:2 title 'truth' with lines linewidth 3 linecolor rgb 'black'
###
unset multiplot
This is the result (with real values):

How to plot tree/graph/web data on gnuplot?

I have a data-set that consist of edges and colors, and I want to plot them on a web-like manner, with lines and circles such as the picture below, and possibly with cluster coloring.
The data is organized like this:
point1a_x point1a_y color
point1b_x point1b_y color
point2a_x point2a_y color
point2b_x point2b_y color
(...)
point2n_x point2n_y color
point2n_x point2n_y color
How would I go about doing it on gnuplot?
Okay, so I figured it out myself and I'll leave the details here to help anyone with the same questions.
Single color graph with labels on the nodes:
This will generate a graph much like the one on the question, with lines connecting circles with labels inside.
plot 'edges.dat' u 1:2 with lines lc rgb "black" lw 2 notitle,\
'edges.dat' u 1:2:(0.6) with circles fill solid lc rgb "black" notitle,\
'edges.dat' using 1:2:($0) with labels tc rgb "white" offset (0,0) font 'Arial Bold' notitle
With little changes it can exaclty match the one on the question picture.
plot 'edges.dat' u 1:2 with lines lc rgb "black" lw 2 notitle,\
'edges.dat' u 1:2:(0.8) with circles linecolor rgb "white" lw 2 fill solid border lc lt 0 notitle, \
'edges.dat' using 1:2:($0) with labels offset (0,0) font 'Arial Bold' notitle
Cluster-colored graph:
unset colorbox
set palette model RGB defined ( 0 0 0 0 , 1 1 0 0 , 2 1 0.9 0, 3 0 1 0, 4 0 1 1 , 5 0 0 1 , 6 1 0 1 )
plot 'edges.dat' u 1:2:3 with lines lc palette notitle,\
'edges.dat' u 1:2:(0.15):3 with circles fill solid palette notitle
The data used on all plots follow this structure:
21.53 9.55 0
24.26 7.92 0
5.63 3.23 1
2.65 1.77 1
5.63 3.23 0
4.27 7.04 0
(...)
The accepted answer didn't quite work out for me. Here is how I had to change it:
The format of the input file
# A vertex has 3 fields: x coordinate, y coordnate and the label
# An edge consists of two points in consecutive lines
# There must be one or more blank lines between each edge.
21.53 9.55 A
24.26 7.92 B
5.63 3.23 C
2.65 1.77 D
5.63 3.23 C
4.27 7.04 E
#...
The big difference compared to the other answer is that the labels belong to vertices, not edges.
Also note that I changed the labels to letters instead of numbers. Labels can be any string and this makes it clearer that they are not sequential indexes in the example.
The plotting command
plot \
'edges.dat' using 1:2 with lines lc rgb "black" lw 2 notitle,\
'edges.dat' using 1:2:(0.6) with circles fill solid lc rgb "black" notitle,\
'edges.dat' using 1:2:3 with labels tc rgb "white" offset (0,0) font 'Arial Bold' notitle
Big change here is that now when plotting the labels we plot the 3rd field instead of the $0 field, which is a sequential number.
I came across this question and thought the data input can be made more user-friendly. In case you need to change x,y coordinates of a certain point you probably don't want to search through all connectors and change the coordinates everywhere accordingly. So, instead the example below is working with node IDs and connecting lines between two IDs.
The x,y coordinates and colors are stored in a string and the function strstrt() is used to create a lookup. The script below is a starting point and can be expanded, e.g. dashed lines, different point shapes, string labels, etc.
The datafile looks like this:
first block: IDs with x,y coordinates and color
second block, separated by two(!) blank lines: IDs to be connected and color of the line.
Data: SO20406346.dat
# ID x y PointColor
1 2.0 8.0 0xffaaaa
2 6.0 9.0 0xaaffaa
3 9.0 6.0 0xaaaaff
4 5.0 5.0 0xffaaff
5 6.0 2.0 0xffffaa
6 1.0 1.0 0xaaffff
73 9.2 1.3 0xcccccc
A 8.0 8.0 0xcccccc
XY 2.0 4.0 0xcccccc
# ID1 ID2 LineColor
1 4 0x0000ff
2 4 0x000000
3 4 0x00ff00
4 4 0x000000
5 4 0x000000
6 5 0xff0000
73 3 0xcccccc
73 4 0xcccccc
73 5 0xcccccc
A 2 0xcccccc
A 3 0xcccccc
XY 1 0xcccccc
XY 4 0xcccccc
XY 6 0xcccccc
Edit: changed to work with string "IDs" as well.
Script: (works for gnuplot>=4.6.0, March 2012)
### plot a node graph
reset
FILE = "SO20406346.dat"
IdIdxs = XYs = ' '
stats FILE u (IdIdxs=IdIdxs.sprintf("%s:%d ",strcol(1),$0), \
XYs=XYs.sprintf("%g %g ",$2,$3)) index 0 nooutput
Px(i) = real(word(XYs,2*i+1))
Py(i) = real(word(XYs,2*i+2))
getIdx(col) = (c0=strstrt(IdIdxs,sprintf(" %s:",strcol(col))), \
c1=strstrt(IdIdxs[c0+1:],' ')+c0, \
s0=IdIdxs[c0:c1], c2=strstrt(s0,':'), int(s0[c2+1:]))
set size ratio 1
set key noautotitle
set offsets 0.25,0.25,0.25,0.25
plot FILE index 1 u (idx0=getIdx(1),x0=Px(idx0)):(y0=Py(idx0)): \
(idx1=getIdx(2),Px(idx1)-x0):(Py(idx1)-y0):3 w vec lw 2 lc rgb var nohead, \
'' index 0 u 2:3:4 w p pt 7 ps 6 lc rgb var, \
'' index 0 u 2:3 w p pt 6 ps 6 lc rgb "black", \
'' index 0 u 2:3:1 w labels
### end of script
Result:

How to Create a Spider Plot in Gnuplot?

I would like to produce a spider (aka radar/star) plot using Gnuplot where different axes have independent scales. I am able to produce such a plot using OriginPro (commercial), but with Gnuplot I am only able to set a radar plot with uniform scale.
The (csv file) dataset looks like the following (first row is column labels):
# FEATURE, Product_A, Product_B, Product_C, Product_D
attribute_1, 2, 10, 7, 3.5
attribute_2, 1, 0.5, 3,4
attribute_3, 37, 58, 49, 72
attribute_4, 1985, 1992, 2006, 2010
attribute_5, 0.1, 0.5, 0.3, 0.8
and the plot I am looking for is this one: https://www.dropbox.com/s/uvqubzqvm6puhb8/spider.pdf -
As you can see each axis stands for a different attribute, and has its own scale.
I guess the Gnuplot starting code is:
set polar
set grid polar
set angles degrees
set size square
set style data filledcurves
But I don't know how to proceed. Any suggestions?
here's a hack attempt..
set nokey
set polar
set grid polar
set angles degrees
set size square
set style data lines
a1=0
a2=30
a3=100
a4=200
a5=300
set arrow nohead from 0,0 to first 10*cos(a1) , 10*sin(a1)
set arrow nohead from 0,0 to first 10*cos(a2) , 10*sin(a2)
set arrow nohead from 0,0 to first 10*cos(a3) , 10*sin(a3)
set arrow nohead from 0,0 to first 10*cos(a4) , 10*sin(a4)
set arrow nohead from 0,0 to first 10*cos(a5) , 10*sin(a5)
set xrange [-10:10]
set yrange [-10:10]
plot '-' using ($1==1?a1:($1==2?a2:($1==3?a3:($1==4?a4:($1==5?a5:$1))))):2 lt 2
1 4
2 8
3 6
4 9
5 5
1 4
Here is a suggestion for a "spider-plot" taken from my collection.
Since it uses data from a datablock instead from a file (because it's easier to address certain lines, e.g. via $Data[1]), therefore, it requires gnuplot >=5.2.0.
The actual data is in $Data and some settings for ranges and custom offset adjustments are in $Settings.
The number of axes is automatically adjusted if you add some more rows in $Data and $Settings. Data needs to be separated by whitespace, because the gnuplot function word(string,number) is used to extract some values.
I hope it is more or less self-explaining. Comments, report of bugs or improvements are welcome.
Code:
### spider plot/chart with gnuplot
# also known as: radar chart, web chart, star chart, cobweb chart,
# radar plot, web plot, star plot, cobweb plot, etc. ...
reset session
set size square
unset tics
set angles degree
set key top left
# Data
$Data <<EOD
SpiderData "Product A" "Product B" "Product C" "Product D"
Colors red green blue violet
"attribute 1" 2 10 7 3.5
"attribute 2" 1 0.5 3 4
"attribute 3" 37 58 49 72
"attribute 4" 1985 1992 2006 2010
"attribute 5" 0.1 0.5 0.3 0.8
EOD
HeaderLines = 2
# Settings for scale and offset adjustments
# axis min max tics axisLabelXoff axisLabelYoff ticLabelXoff ticLabelYoff
$Settings <<EOD
1 0 12 6 0.00 -0.02 -0.05 0.00
2 0 6 6 0.00 0.05 0.00 0.05
3 30 90 6 0.00 0.00 0.05 0.03
4 1980 2016 6 0.00 0.00 0.09 -0.02
5 0 1.2 6 0.00 0.05 0.00 -0.05
EOD
# General settings
DataColCount = words($Data[1])-1
AxesCount = |$Data|-HeaderLines
AngleOffset = 90
Max = 1
d=0.1*Max
Direction = -1 # counterclockwise=1, clockwise = -1
# Tic settings
TicCount = 6
TicValue(axis,i) = real(i)*(word($Settings[axis],3)-word($Settings[axis],2)) \
/ word($Settings[axis],4)+word($Settings[axis],2)
TicLabelPosX(axis,i) = PosX(axis,i/TicCount) + word($Settings[axis],7)
TicLabelPosY(axis,i) = PosY(axis,i/TicCount) + word($Settings[axis],8)
TicLen = 0.03
TicdX(axis,i) = 0.5*TicLen*cos(alpha(axis)-90)
TicdY(axis,i) = 0.5*TicLen*sin(alpha(axis)-90)
# Functions
alpha(axis) = (axis-1)*Direction*360.0/AxesCount+AngleOffset
PosX(axis,R) = R*cos(alpha(axis))
PosY(axis,R) = R*sin(alpha(axis))
Scale(axis,value) = real(value-word($Settings[axis],2))/(word($Settings[axis],3)-word($Settings[axis],2))
# Spider settings
set style arrow 1 dt 1 lw 1.0 lc -1 head # style for axes
set style arrow 2 dt 2 lw 0.5 lc -1 nohead # style for weblines
set style arrow 3 dt 1 lw 1 lc -1 nohead # style for axis tics
set samples AxesCount
set isosamples TicCount
set urange[1:AxesCount]
set vrange[1:TicCount]
do for [i=1:DataColCount] { # set linetypes/colors
set linetype i lc rgb word($Data[2],i+1)
}
set style fill transparent solid 0.2
set xrange[-Max-4*d:Max+4*d]
set yrange[-Max-4*d:Max+4*d]
plot \
'+' u (0):(0):(PosX($0,Max+d)):(PosY($0,Max+d)) w vec as 1 not, \
$Data u (PosX($0+1,Max+2*d)+word($Settings[$0+1],5)): \
(PosY($0+1,Max+2*d)+word($Settings[$0+1],6)):1 every ::HeaderLines w labels center enhanced not, \
'++' u (PosX($1,$2/TicCount)):(PosY($1,$2/TicCount)): \
(PosX($1+1,$2/TicCount)-PosX($1,$2/TicCount)): \
(PosY($1+1,$2/TicCount)-PosY($1,$2/TicCount)) w vec as 2 not, \
'++' u (PosX($1,$2/TicCount)-TicdX($1,$2/TicCount)): \
(PosY($1,$2/TicCount)-TicdY($1,$2/TicCount)): \
(2*TicdX($1,$2/TicCount)):(2*TicdY($1,$2/TicCount)) \
w vec as 3 not, \
for [i=1:DataColCount] $Data u (PosX($0+1,Scale($0+1,column(i+1)))): \
(PosY($0+1,Scale($0+1,column(i+1)))) every ::HeaderLines w filledcurves lt i title word($Data[1],i+1), \
'++' u (TicLabelPosX($1,$2)):(TicLabelPosY($1,$2)): \
(sprintf("%g",TicValue($1,$2))) w labels font ",8" not
### end of code
Result:
The answer by #george helped me figure out how to rearrange the dataset, in order to pick from it the corresponding attribute data.
Because I was also looking for different range scales for the different spider axes, in addition to #george's suggestion, I thought that an axis-specific normalisation to the common [0:1] range, would have the problem solved. The main modification is then related to the using field of the plot command.
The code is fairly lengthy, I'm sure it could be optimised. It could also be merged into a script or a simple C code, in order to let the user decide the number of axes (number of attributes), and the different ranges (min, max) for each specific axis.
The following example is for 5 attributes comparing 2 products. Here is shown the plot result image:
set nokey
set polar
set angles degrees
npoints = 5
a1 = 360/npoints*1
a2= 360/npoints*2
a3= 360/npoints*3
a4= 360/npoints*4
a5= 360/npoints*5
set grid polar 360.
set size square
set style data lines
unset border
set arrow nohead from 0,0 to first 1*cos(a1) , 1*sin(a1)
set arrow nohead from 0,0 to first 1*cos(a2) , 1*sin(a2)
set arrow nohead from 0,0 to first 1*cos(a3) , 1*sin(a3)
set arrow nohead from 0,0 to first 1*cos(a4) , 1*sin(a4)
set arrow nohead from 0,0 to first 1*cos(a5) , 1*sin(a5)
a1_max = 10
a2_max = 5
a3_max = 100
a4_max = 2020
a5_max = 1
a1_min = 0
a2_min = 0
a3_min = 50
a4_min = 1980
a5_min = 0
set label "(0:10)" at cos(a1),sin(a1) center offset char 1,1
set label "(0:5)" at cos(a2),sin(a2) center offset char -1,1
set label "(50:100)" at cos(a3),sin(a3) center offset char -1,-1
set label "(1980:2020)" at cos(a4),sin(a4) center offset char 0,-1
set label "(0:1)" at cos(a5),sin(a5) center offset char 3,0
set xrange [-1:1]
set yrange [-1:1]
unset xtics
unset ytics
set rrange [0:1]
set rtics (""0,""0.25,""0.5,""0.75,""1)
plot '-' using ($1==1?a1:($1==2?a2:($1==3?a3:($1==4?a4:($1==5?a5:$1))))):($1==1?(($2-a1_min)/(a1_max-a1_min)):($1==2?(($2-a2_min)/(a2_max-a2_min)):($1==3?(($2-a3_min)/(a3_max-a3_min)):($1==4?(($2-a4_min)/(a4_max-a4_min)):($1==5?(($2-a5_min)/(a5_max-a5_min)):$1))))) w l
1 8
2 3
3 67
4 2000
5 0.2
1 8
plot '-' using ($1==1?a1:($1==2?a2:($1==3?a3:($1==4?a4:($1==5?a5:$1))))):($1==1?(($2-a1_min)/(a1_max-a1_min)):($1==2?(($2-a2_min)/(a2_max-a2_min)):($1==3?(($2-a3_min)/(a3_max-a3_min)):($1==4?(($2-a4_min)/(a4_max-a4_min)):($1==5?(($2-a5_min)/(a5_max-a5_min)):$1))))) w l
1 6
2 1.5
3 85
4 2010
5 0.5
1 6
The following repo shows a spider chart with homogeneous scales. https://github.com/orey/gnuplot-radarchart
For your particular case, I would:
-Create functions that would normalize all data to fit in the diagram scale,
-Hide tge standard scale,
-Use arrows for the axis,
-Add points with labels for your particular scales and place them with your data functions.
I think inspiration can be found in the repo.

Resources