I want to create a variant of a candlestick in gnuplot that looks like this:
For every category there should be one or two candlesticks and two bars. What I want to display is one statistical measurement (results of a simulation, first candlestick) and one optional measurement (results of an experiment, second candlestick). Both will have a median, the quartiles one and three and min and max.
Additionally the green bar will show the best-case of a formal analysis and the red bar the worst-case of the formal analysis.
So per category there will be at least seven values (five values for the simulation and the two values of the formal analysis) and at most twelve values (the seven values from above plus five values for the experiment).
Unfortunately I do not know how to implement this and I am really thankfull for any help. It does not need to be gnuplot. Qt or jfreechart are also possibilities of which I thought. Maybe even TikZ...
Some example data:
data_sim.txt (for candlestick. Format category|min|q1|median|q3|max)
EthernetMessage#1 0.055280408 0.055681596 0.056091449 0.05641499 0.056776635
EthernetMessage#10 0.040785478 0.047341668 0.048439533 0.082419908 0.128777062
EthernetMessage#11 0.017520593 0.032334507 0.057476335 0.073707177 0.093273343
EthernetMessage#12 0.013744029 0.014562369 0.020228557 0.034301248 0.096911465
EthernetMessage#13 0.022368326 0.023299042 0.035760612 0.04297819 0.123465625
EthernetMessage#14 0.012348243 0.01267815 0.013033673 0.013412192 0.013818397
EthernetMessage#15 0.012543378 0.013067406 0.013464282 0.013810399 0.022771801
EthernetMessage#16 0.013393393 0.013763234 0.014105891 0.014495293 0.01489021
EthernetMessage#17 0.01234332 0.012813941 0.013188793 0.013562078 0.021207808
EthernetMessage#18 0.013218586 0.013824792 0.014271764 0.098167281 0.186240002
EthernetMessage#19 0.012337817 0.01298168 0.013586632 0.018008508 0.022710523
data_exp.txt (for optional candlestick. Format category|min|avg|max)
EthernetMessage#1 0.05524 0.05558 0.0559
EthernetMessage#10 0.03843 0.065575 0.1505
EthernetMessage#11 0.0184 0.06649 0.11854
EthernetMessage#12 0.0135 0.03132 0.1233
EthernetMessage#13 0.0222 0.04964 0.14111
EthernetMessage#14 0.01201 0.01233 0.01265
EthernetMessage#15 0.01172 0.01202 0.01236
EthernetMessage#16 0.01303 0.01334 0.01367
EthernetMessage#17 0.01172 0.01315 0.02388
EthernetMessage#18 0.0126 0.056613333 0.19049
EthernetMessage#19 0.01172 0.01419 0.0185
data_ana.txt (for the bars. Format category|best_case|worst_case)
EthernetMessage#1 0.05528 0.209579
EthernetMessage#10 0.03832 0.35686
EthernetMessage#11 0.01752 0.35582
EthernetMessage#12 0.013744 0.35582
EthernetMessage#13 0.022368 0.35582
EthernetMessage#14 0.012336 0.133683
EthernetMessage#15 0.012336 0.145283
EthernetMessage#16 0.013391 0.133683
EthernetMessage#17 0.012336 0.145283
EthernetMessage#18 0.013216 0.643879
EthernetMessage#19 0.012336 0.231979
Here is a possible implementation with gnuplot (I'm not sure, if I interpreted the data_sim.txt columns correctly):
reset
set boxwidth 0.2 absolute
set style line 1 linecolor rgb '#5555CC' # for sim boxes
set style line 2 linecolor rgb '#BBBBff' # for exp boxes
set style line 3 linecolor rgb '#AE1100' lw 3 # for worst case
set style line 4 linecolor rgb '#6EB043' lw 3 # for best case
set style line 5 linecolor rgb 'black' # for medians
set style data candlesticks
plot 'data_ana.txt' using 0:2:(0.3):(0.001):xtic(stringcolumn(1)[16:*]) with boxxyerrorbars ls 4 title 'best case',\
'' using 0:3:(0.3):(0.001) with boxxyerrorbars ls 3 title 'worst case',\
'data_sim.txt' using ($0-0.2):3:2:6:5 whiskerbars ls 1 title 'simulation',\
'' using ($0-0.2):4:4:4:4 ls 5 notitle,\
'data_exp.txt' using ($0+0.2):2:2:4:4 ls 2 title 'experiment',\
'' using ($0+0.2):3:3:3:3 ls 5 notitle
with the result (using 4.6.3):
Some remarks to the code:
The boxes are plotted like How to combine two box-whisker plots into one using gnuplot, the medians must be added separately.
Each "block" is positioned using the row number (column(0), or $0). So the difference between two lines is 1, which is used to estimate the boxwidth and the shifted positions of the simulation and experimental data.
The xticlabels are positioned together with the "worst case" bars, because most of the other boxes or bars are shifted to the left or to the right.
To use the complete entry of the first column as xticlabels, use xtic(1), which is a shortcut for xticlabel(stringcolumn(1)). In that case you should also use set xtic rotate to have the labels typeset vertically.
this almost solved what I wanted to do. I changed it slightly to
reset
set boxwidth 0.2 absolute
set style line 1 linecolor rgb '#5555CC' # for sim boxes
set style line 2 linecolor rgb '#BBBBff' # for exp boxes
set style line 3 linecolor rgb '#AE1100' lw 3 # for worst case
set style line 4 linecolor rgb '#6EB043' lw 3 # for best case
set style line 5 linecolor rgb 'black' # for medians
set style data candlesticks
set xtics rotate by -45
plot 'data_ana.txt' using 0:2:(0.3):(0.001):xticlabels(1) with boxxyerrorbars ls 4 title 'best case',\
'' using 0:3:(0.3):(0.001) with boxxyerrorbars ls 3 title 'worst case',\
'data_sim.txt' using ($0-0.2):3:2:6:5 whiskerbars ls 1 title 'simulation',\
'' using ($0-0.2):4:4:4:4 ls 5 notitle,\
'data_exp.txt' using ($0+0.2):3:2:4:3 whiskerbars ls 2 title 'experiment',\
'' using ($0+0.2):3:3:3:3 ls 5 notitle
Now I have what I wanted.
Best,
Jan
Related
I'm attempting to use gnuplot v5.4 to generate multiple graphs from one data set, though using select data from the set per graph.
I generate stats for a small program I'm developing, and write them to a CSV file:
(This CSV format is just what I've made the best progress with - I'm open to changing)
TotalPlayerCount,22
BluePlayerCount,10
RedPlayerCount,12
BluePlayerScoreTotal,50
RedPlayerScoreTotal,60
The following gives me the below graph:
cat <<"EOF" | gnuplot -p
$db <<DB
TotalPlayerCount,22
BluePlayerCount,10
RedPlayerCount,12
BluePlayerScoreTotal,50
RedPlayerScoreTotal,60
DB
set terminal windows size 2000,1000 enhanced font 'Arial,8'
set datafile separator ','
set yrange [0:100]
set boxwidth 0.1 relative
set style fill solid 1.0
plot $db using 2:xticlabel(1) notitle with boxes linestyle 1
EOF
I'm aiming for this:
which I have achieved using this:
cat <<"EOF" | gnuplot -p
$db <<DB
TotalPlayerCount,22
BluePlayerCount,10
RedPlayerCount,12
BluePlayerScoreTotal,50
RedPlayerScoreTotal,60
DB
set terminal windows size 2000,1000 enhanced font 'Arial,8'
set datafile separator ','
set yrange [0:100]
set boxwidth 0.1 relative
set style fill solid 1.0
set multiplot layout 1,2
plot $db using 2:xticlabel(1) every ::1::2 notitle with boxes linestyle 1
plot $db using 2:xticlabel(1) every ::3::4 notitle with boxes linestyle 1
unset multiplot
EOF
Is there a better or more idiomatic way to select from the data file what 'rows' to plot? These indices (in the every clause) work OK, but seem fragile.
I have previously used the trick where a ternary returning undefined in the using will cause gnuplot to ignore that row (e.g. maybe I could use it to select based on string compare) but that doesn't seem much more elegant either and I don't really enjoy how complex it makes the plot command.
One possibility that gives you a more "readable" syntax would be to use columnheaders, for which you would need to transpose your dataset. You don't necessarily need to use comma; spaces or tabs will do the trick as well:
$db <<DB
TotalPlayerCount BluePlayerCount RedPlayerCount BluePlayerScoreTotal RedPlayerScoreTotal
22 10 12 50 60
DB
Set up the layout:
set xrange [0:3]
set yrange [0:100]
set boxwidth 0.5
set style fill solid 1.0
Now you can select the column that you want to plot with column("string"), which will give you the correct y value. As for the x value, I simply took the constant number 1 for the first plot and 2 for the second one. In order to produce xticlabels one has to repeat the string:
plot $db u (1):(column("BluePlayerCount")):xticlabels("BluePlayerCount") w boxes not, \
$db u (2):(column("RedPlayerCount")):xticlabels("RedPlayerCount") w boxes not
Alternatively, you could delete the xticlabels part from the plot command and instead use: set xtics ("BluePlayerCount" 1, "RedPlayerCount" 2)
You could also automate the plot even further:
whattoplot_1 = "BluePlayerCount"
whattoplot_2 = "RedPlayerCount"
x_pos_1 = 1
x_pos_2 = 2
set xtics (whattoplot_1 x_pos_1, whattoplot_2 x_pos_2)
plot $db u (x_pos_1):(column(whattoplot_1)) w boxes not, \
$db u (x_pos_2):(column(whattoplot_2)) w boxes not
Depending on what you want to achieve in the end, you might consider using arrays and iterate over the elements:
array whattoplot[2] = ["BluePlayerCount", "RedPlayerCount"]
plot for [i=1:|whattoplot|] $db u (i):(column(whattoplot[i])) w boxes not
I hope this gives you some inspiration for how to proceed!
If you are flexible with the input data, I would organize it in the following way:
Instead of dumping everything into one file and separating it again, I would create two files, e.g. 'Counts.dat' and 'Scores.dat'.
In the (copy&paste) example below it is included in the code with datablocks $Counts and $Scores, however, if you have your data in files, simply skip the datablocks and in the plot command change it to 'Counts.dat' and 'Scores.dat', respectively.
You don't necessarily need the total count in your data, gnuplot can do this for you.
Furthermore, in the example below I introduced a third column for the color of the boxes. Check the following example as starting point for further optimization.
Code:
### multiplot with boxes and total sum
reset session
$Counts <<EOD
Red 12 0xff0000
Green 5 0x00cc00
Blue 10 0x0000ff
Yellow 7 0xffff00
EOD
$Scores <<EOD
Red 60 0xff0000
Green 30 0x00cc00
Blue 50 0x0000ff
Yellow 80 0xffff00
EOD
set yrange[0:100]
set boxwidth 0.5 relative
set style fill solid 1.0
set key left noautotitle
set grid x,y
set multiplot layout 1,2
set title "Counts"
plot sum=0 $Counts u 0:(sum=sum+column(2),column(2)):3:xtic(1) w boxes lc rgb var, \
keyentry w p ps 0 ti sprintf("Total count: %d",sum)
set title "Scores"
plot $Scores u 0:2:3:xtic(1) w boxes lc rgb var
unset multiplot
### end of code
Result:
Addition: (all data in one datablock or file)
Code:
### multiplot with boxes and total sum in a single file
reset session
$AllInOne <<EOD
# counts
Red 12 0xff0000
Green 5 0x00cc00
Blue 10 0x0000ff
Yellow 7 0xffff00
# scores
Red 60 0xff0000
Green 30 0x00cc00
Blue 50 0x0000ff
Yellow 80 0xffff00
EOD
set yrange[0:100]
set boxwidth 0.5 relative
set style fill solid 1.0
set key left noautotitle
set grid x,y
set multiplot layout 1,2
set title "Counts"
plot sum=0 $AllInOne u 0:(sum=sum+column(2),column(2)):3:xtic(1) index 0 w boxes lc rgb var, \
keyentry w p ps 0 ti sprintf("Total count: %d",sum)
set title "Scores"
plot $AllInOne u 0:2:3:xtic(1) index 1 w boxes lc rgb var
unset multiplot
### end of code
I was wondering if it is possible to add a coloured line to a label command in gnuplot? That is, say I would like to add a red line after some text in a label command:
set label "some text here which is then followed by a red horizontal line -----" at 100,200 front
Basically, I want to mimic the usual presentation of the key in gnuplot in a label command. I already have one key and another key is not allowed within the same plot environment, so I want to manually construct a second key through the label command.
Thanks in advance.
I would do it the following way. Check the details of help arrow and help label.
Edit: using separate lines and labels is certainly more code but you have full flexibility. I guess it depends on what exactly you want to do.
Code:
### labels with lines
reset session
set size ratio -1
set arrow 1 from 4,0 to 7,0 lc "red" lw 2 nohead
set label 1 at 4,0 "Some text" right offset -1,0
set arrow 2 from 2,-2 to 5,-2 lc "red" lw 2 dt 3 nohead
set label 2 at 5,-2 "Some text" left offset 1,0
set arrow 3 from -6,5 to -2,5 lc "red" lw 2 dt 1 nohead
set label 3 at -4,5 "Some text" center offset 0,-1
set arrow 4 from -6,-2 length 5.5 angle 45 lc "red" lw 2 dt 3 nohead
set label 4 at -6,-2 "Some text" font ",14" right rotate by 45 offset -1,0
plot x w l lc "blue"
### end of code
Result:
You can have a second key by plotting data that is all invalid (NaN, not a number). For example,
cat >data <<\!
17 15
18 5
19 10
21 7
!
gnuplot -persist <<\!
plot "data" u 1:2 with lines title "plot1", \
"" u (NaN):(NaN) with lines title "plot2"
!
You can use a plot clause with the keyword keyentry rather than a file name to generate an extra title and line/point/fill sample for the key. You can also use the keyword at <x-pos>,<y-pos> to place this extra title somewhere else on the page.
Examples from the on-line demo set:
custom key generation
extra key entries
Quick example here:
set xrange [0:20]
plot x**2, x**3, \
keyentry with lines dt '-' lc "red" title "Extra title" at graph 0.25, graph 0.75
I am plotting a 3D 'fence plot' with multiple colors for each fence. My sample data can be found here:
https://gist.github.com/anonymous/a926221ea96e92e86332
I plot this data using this:
colors = "red red red red red"
splot for [i=1:words(colors)] 'input.sep.txt' index i u 2:1:3 w lines lc rgb word(colors,i)
The lines are drawn without issue, and I believe they are drawn correctly. My question is this: how do I fill below the line so that it looks like a solid wall (i.e. all the way down to the 0 z value)? I tried using w pm3d, however this did not actually plot anything visible on the axis.
The best option you have is to use pm3d. For this to work you must change your data file a bit: You must duplicate very line, change the z-value of the duplicate to 0 and add a new line, i.e. your first two data lines
1 1 2
2 1 4
must become
1 1 2
1 1 0
2 1 4
2 1 0
and so on. You still need the two consecutive empty lines later to separate different "walls".
If you have control over your data output, you could change your output routine, or you can use a command line tool like sed
sed 's/^\([0-9]* [0-9]* \)\(.*\)$/&\n\1 0\n/' gistfile1.txt
or awk:
awk '1; {print $1,$2,0,"\n"}' gistfile1.txt
to do the conversion. Of course this can be done on-the-fly from within gnuplot. A complete, working script is then:
filename = 'gistfile1.txt'
sed = '< sed ''s/^\([0-9]* [0-9]* \)\(.*\)$/&\n\1 0\n/'' '
set autoscale cbfix
set palette defined (0 'red', 1 'blue')
set pm3d depthorder
unset colorbox
unset key
set ticslevel 0
splot sed.filename using 1:2:3:(column(-2)) with pm3d
and the result using gnuplot 4.6.5 with your example data is:
Some additional notes:
The fourth column is used to select a different value than the z-value for the coloring.
column(-2) uses the block number (adjacent blocks are delimited by two empty lines) as color index.
Points belonging to different data blocks aren't connected.
With set autoscale cbfix you can better control the colors used for the planes.
If you know, that you have e.g. three planes which should have specific colors you could also use set palette defined (0 'red', 1 'green', 2 'blue').
This is a workaround rather than a proper solution, but it might work for you. Play with the filledcurves option which is not really designed for 3D plotting. What you have, as it is, would look like:
colors = "red red red red red"
splot for [i=1:words(colors)] 'input.sep.txt' index i u 2:1:3 w filledcurve lc rgb \
word(colors,i), for [i=1:words(colors)] 'input.sep.txt' index i u 2:1:3 w l lc "black" lw 2
Using a tricksy trick with the set dgrid3d command, you can increase the number of vertical lines that get drawn (set dgrid3d 100,2 in this case):
Until you're happy with the result (set dgrid3d 200,2):
I like following linespoints plotting style:
http://www.gnuplotting.org/join-data-points-with-non-continuous-lines/
However, I have encountered an issue when I plot several lines with this style:
As you can see the second series of points blank-out also the first series (lines and points), what I don't want to happen.
Feature of gnuplot which makes this possible is pointinterval and pointintervalbox.
Documentation of gnuplot:
A negative value of pointinterval, e.g. -N, means that point symbols
are drawn only for every Nth point, and that a box (actually circle)
behind each point symbol is blanked out by filling with the background
color. The command set pointintervalbox controls the radius of this
blanked-out region. It is a multiplier for the default radius, which
is equal to the point size.
http://www.bersch.net/gnuplot-doc/set-show.html#set-pointintervalbox
Since the doc says, fill with background color I was hoping using a transparent background the issue could be resolved, but it seems to be that the color white is used.
Gnuplot version
gnuplot> show version long
G N U P L O T
Version 5.0 patchlevel 0 last modified 2015-01-01
Copyright (C) 1986-1993, 1998, 2004, 2007-2015
Thomas Williams, Colin Kelley and many others
gnuplot home: http://www.gnuplot.info
faq, bugs, etc: type "help FAQ"
immediate help: type "help" (plot window: hit 'h')
Compile options:
-READLINE +LIBREADLINE +HISTORY
-BACKWARDS_COMPATIBILITY +BINARY_DATA
+GD_PNG +GD_JPEG +GD_TTF +GD_GIF +ANIMATION
-USE_CWDRC +HIDDEN3D_QUADTREE
+DATASTRINGS +HISTOGRAMS +OBJECTS +STRINGVARS +MACROS +THIN_SPLINES +IMAGE +USER_LINETYPES +STATS +EXTERNAL_FUNCTIONS
Minimal Working Example (MWE):
gnuplot-space-line-mark-style.gp
reset
set terminal pngcairo transparent size 350,262 enhanced font 'Verdana,10'
show version
set output 'non-continuous_lines.png'
set border linewidth 1.5
set style line 1 lc rgb '#0060ad' lt 1 lw 2 pt 7 pi -1 ps 1.5
set style line 2 lc rgb '#0020ad' lt 1 lw 2 pt 7 pi -1 ps 1.5
set pointintervalbox 3
unset key
set ytics 1
set tics scale 0.75
set xrange [0:5]
set yrange [0:4]
plot 'plotting_data1.dat' with linespoints ls 1,\
'plotting_data2.dat' with linespoints ls 2
plotting_data1.dat
# X Y
1 2
2 3
3 2
4 1
plotting_data2.dat
# X Y
1.2 2.4
2 3.5
3 2.5
4 1.2
UPDATE
A working pgfplots solution is given on tex.stackoverflow.com
You can do a lot with gnuplot. It's just a matter of how complicated you allow it to get.
You can realize the gap by a two step plotting. First: only with points and second: with vectors which are lines between the points shortened by performing a bit of geometry calculations.
The parameter L1 determines the gap and needs to be adjusted to the data and graph scale. Tested with gnuplot 5.0 and 5.2.
Revised version:
Here is the version which creates gaps independent of the terminal size and the graph scale. It just requires bit more scaling. However, since it requires the size of terminal and graph which are stored in GPVAL_...-variables which you only get after plotting, therefere the procedure unfortunately requires replotting.
I'm not sure whether this works for all terminals. I just tested on a wxt terminal.
Empirical findings (for wxt-terminal on Win7):
pointsize 100 (ps) corresponds to 600 pixels (px), hence: Rpxps=6 (ratio pixel to pointsize )
term size 400,400 (px) corresponds to 8000,8000 terminal units (tu), hence: Rtupx=20 (ratio terminal units to pixels)
Edit: the factor Rtupx apparently is different for different terminals: wxt: 20, qt: 10, pngcairo: 1, you could use the variable GPVAL_TERM for checking the terminal.
Rtupx = 1. # for pngcairo terminal 1 tu/px
if (GPVAL_TERM eq "wxt") { Rtupx = 20. } # 20 tu/px, 20 terminal units per pixel
if (GPVAL_TERM eq "qt") { Rtupx = 10. } # 10 tu/px, 10 terminal units per pixel
The ratios of axis units (au) to terminal units (tu) are different for x and y and are:
Rxautu = (GPVAL_X_MAX-GPVAL_X_MIN)/(GPVAL_TERM_XMAX-GPVAL_TERM_XMIN)
Ryautu = (GPVAL_Y_MAX-GPVAL_Y_MIN)/(GPVAL_TERM_YMAX-GPVAL_TERM_YMIN)
The variable GapSize is given in pointsize units. Actually, the real gap size depends on the pointsize (and also linewidth of the line). For simplicity, here gap size means the distance from the center of the point to where the line starts. So, GapSize=1.5 when having pointsize 1.5 will result in a gap of 0.75 on each side. L3(n) from the earlier version is now replaced by L3px(n) in pixel dimensions and L1 from the earlier version is not needed anymore.
Code:
### "linespoints" with gaps between lines and points
reset session
$Data1 <<EOD
# X Y
0 3
1 2
1.5 1
3 2
4 1
EOD
$Data2 <<EOD
0 0
1 1
2 1
2 2
3 1
3.98 0.98
EOD
GapSize = 1.5
Rtupx = 20. # 20 tu/px, 20 terminal units per pixel
Rpxps = 6. # 6 px/ps, 6 pixels per pointsize
# Ratio: axis units per terminal units
Rxautu(n) = (GPVAL_X_MAX-GPVAL_X_MIN)/(GPVAL_TERM_XMAX-GPVAL_TERM_XMIN)
Ryautu(n) = (GPVAL_Y_MAX-GPVAL_Y_MIN)/(GPVAL_TERM_YMAX-GPVAL_TERM_YMIN)
dXpx(n) = (x3-x0)/Rxautu(n)/Rtupx
dYpx(n) = (y3-y0)/Ryautu(n)/Rtupx
L3px(n) = sqrt(dXpx(n)**2 + dYpx(n)**2)
x1px(n) = dXpx(n)*GapSize*Rpxps/L3px(n)
y1px(n) = dYpx(n)*GapSize*Rpxps/L3px(n)
x2px(n) = dXpx(n)*(L3px(n)-GapSize*Rpxps)/L3px(n)
y2px(n) = dYpx(n)*(L3px(n)-GapSize*Rpxps)/L3px(n)
x1(n) = x1px(n)*Rtupx*Rxautu(n) + x0
y1(n) = y1px(n)*Rtupx*Ryautu(n) + y0
x2(n) = x2px(n)*Rtupx*Rxautu(n) + x0
y2(n) = y2px(n)*Rtupx*Ryautu(n) + y0
set style line 1 pt 7 ps 1.5 lc rgb "black"
set style line 2 lw 2 lc rgb "black
set style line 3 pt 7 ps 1.5 lc rgb "red"
set style line 4 lw 2 lc rgb "red"
plot \
$Data1 u (x3=NaN, y3=NaN,$1):2 w p ls 1 notitle, \
$Data1 u (y0=y3,y3=$2,x0=x3,x3=$1,x1(0)):(y1(0)): \
(x2(0)-x1(0)):(y2(0)-y1(0)) w vectors ls 2 nohead notitle, \
$Data2 u (x3=NaN, y3=NaN,$1):2 w p ls 3 notitle, \
$Data2 u (y0=y3,y3=$2,x0=x3,x3=$1,x1(0)):(y1(0)): \
(x2(0)-x1(0)):(y2(0)-y1(0)) w vectors ls 4 nohead notitle
replot
### end of code
Result: (two different terminal sizes)
Explanations:
Question: Why is there the argument (n) for L3(n), x1(n), y1(n), x2(n), y2(n)?
n is always 0 when L3(n),... are computed and is not used on the right hand side.
Answer:
To make them non constant-expressions. Alternatively, one could
add x0,x3,y0,y3 as variables, e.g. L3(x0, y0, x3, y3); however, the
compactness would be lost.
Question: What does the using part in plot $Data1 using (x3=NaN,y3=NaN,$1):2 mean?
Answer:
(,) is called a serial evaluation which is documented under the
section Expressions > Operator > Binary in the gnuplot documentation
(only v4.4 or newer).
Serial evaluation occurs only in parentheses and is guaranteed to
proceed in left to right order. The value of the rightmost subexpression
is returned.
This is done here for the initialialization of (x3,y3) for the
subsequent plot of the line segments as vectors. It is irrelevant for
the plotting of points.
Question: How does this draw N-1 segments/vectors for N points?
Answer:
Setting x3=NaN, y3=NaN when plotting points ensures that for the
first data point the initial data point (x0,y0) is set to (NaN,NaN)
which has the consequence that the evaluation of x1(0) and y1(0) also returns NaN.
Gnuplot in general skips points with NaN, i.e. for the first
data point no vector is drawn. The code draws the line between the
first and second point when the iteration reaches the second point.
Question: How does the second plot '' u ... iterates over all points?
Answer:
gnuplot> h special-filenames explains this:
There are a few filenames that have a special meaning: '', '-', '+' and '++'.
The empty filename '' tells gnuplot to re-use the previous input file in the
same plot command. So to plot two columns from the same input file:
plot 'filename' using 1:2, '' using 1:3
Question: Do we need the parentheses around (y1(0))?
Answer: gnuplot> h using explains this:
Each may be a simple column number that selects the value from one
field of the input file, a string that matches a column label in the first
line of a data set, an expression enclosed in parentheses, or a special
function not enclosed in parentheses such as xticlabels(2).
I have used gnuplot succesfully to plot boxplots. But now I would like to stick to gnuplot for all my plotting needs and looking to do something that eg. Prism can do:
http://www.graphpad.com/support/faqid/132/
I only have two columns of data (before and after) and want all pairs to be joined up with a line. If anyone has any idea, it would be great.
That is not possible out of the box, so it requires some fiddling.
The xtics are set manually, 0 is the x-value of 'Before', 1 for 'After'. These numerical values must be used explicitely later in the plots.
The lines are plotted as arrows without heads. Using lc variable (i.e. linecolor variable), we can use the last column of the using statement to select the color from the respective line type.
The 'Before' points are plotted first. Unfortunately, there is no option pointtype variable, so I use the plot for iteration to assign each point a different pointtype (pt).
I use the stats command to determine the number of points to plot. To get the total count, I must sum up the records, which are the inside points, and the outofrange points, because the classification is done based on the first column's value, which conflict with the 'manual' xtics settings for the 'Before' and 'After' labels.
These are the main points. Of course, there are many other possibilities (using line styles etc.), but should be a good starting point.
The script is:
reset
file='beforeafter.txt'
set xtics ('Before' 0, 'After' 1)
set xrange [-0.2:1.2]
set offset 0,0,0.2,0.2
stats file nooutput
cnt = int(STATS_records+STATS_outofrange)
plot for [i=0:cnt-1] file using (0):1 every ::i::i with points lc i+1 pt (6+i) ps 2 t '',\
for [i=0:cnt-1] file using (1):2 every ::i::i with points lc i+1 pt (6+i) ps 2 t '',\
file using (0):1:(1):($2-$1):($0+1) with vectors nohead lc variable t ''
With the test data beforeafter.txt:
1 5.5
2 0.3
3 3
And you get the result:
Using line styles
Another variant uses line styles to set the color, line type, and point type. For the iterations you must use explicitely ls (i+1), whereas for the vectors the as variable (arrowstyle variable) is used. With the lc variable it is not possible to set different dash patterns for the arrows.
So here is a, in my opinion, much more readable and flexible variant:
reset
set termoption dashed
file='beforeafter.txt'
set xtics ('Before' 0, 'After' 1)
set xrange [-0.2:1.2]
set offset 0,0,0.2,0.2
stats file nooutput
cnt = int(STATS_records+STATS_outofrange)
set style line 1 lt 1 pt 5 ps 2 lw 2 lc rgb '#AE1100'
set style line 2 lt 2 pt 7 ps 2 lw 2 lc rgb '#6EB043'
set style line 3 lt 3 pt 9 ps 2 lw 2 lc rgb '#7777ff'
set for [i=1:3] style arrow i ls i nohead
unset key
plot file using (0):1:(1):($2-$1):($0+1) with vectors as variable,\
for [i=0:cnt-1] file using (0):1 every ::i::i with points ls (i+1),\
for [i=0:cnt-1] file using (1):2 every ::i::i with points ls (i+1)
With the result: