GNUPLOT - Two columns histogram with values on top of bars - gnuplot

yesteraday I made a similar question (this one). I could not display the value on top of bar in a gnuplot histogram. I lost many time because I couldn't find really good documentation about it, and I only can find similar issues on differents websites.
I lost many time with that but fortunately someone give me the solution. Now I am having a similar issue with an histogram with two bars, in which I have to put on top of both bars its value. I am quite near, or that is what I think, but I can't make it work properly. I am changing the script and regenerating the graph many times but I am not sure of what I am doing.
script.sh
#!/usr/bin/gnuplot
set term postscript
set terminal pngcairo nocrop enhanced size 600,400 font "Siemens Sans,8"
set termoption dash
set output salida
set boxwidth 0.8 absolute
set border 1
set style fill solid 1.00 border lt -1
set key off
set style histogram clustered gap 1 title textcolor lt -1
set datafile missing '-'
set style data histograms
set xtics border in scale 0,0 nomirror autojustify
set xtics norangelimit
set xtics ()
unset ytics
set title titulo font 'Siemens Sans-Bold,20'
set yrange [0.0000 : limite1] noreverse nowriteback
set y2range [0.0000 : limite2] noreverse nowriteback
show style line
set style line 1 lt 1 lc rgb color1 lw 1
set style line 2 lt 1 lc rgb color2 lw 1
## Last datafile plotted: "immigration.dat"
plot fuente using 2:xtic(1) ls 1 ti col axis x1y1, '' u 3 ls 2 ti col axis x1y2, '' u 0:2:2 with labels offset -3,1 , '' u 0:2:3 with labels offset 3,1
I am modifying the last code line, because is here where I set the labels. I have been able to show both labels, but in bad positions, I have also been able to show one of the labels in the right position but no the other. I have been able to show almost everything but the thing that I want. This is the graph that generates the script.
output.png
This is the source file that I use for generating the graph
source.dat
"Momento" "Torre 1" "Torre 2"
"May-16" 1500.8 787.8
"Jun-16" 1462.3 764.1
"Jul-16" 1311.2 615.4
"Ago-16" 1199.0 562.0
"Sep-16" 1480.0 713.8
"Oct-16" 1435.1 707.8
And that's the command that I execute with the parameters set
gnuplot -e "titulo='Energía consumida por torre (MWh)'; salida='output.png'; fuente='source.dat'; color1='#FF420E'; color2='#3465A4'; limite1='1800.96'; limite2='945.36'" script.sh
I think that is quite obvious what I am pretending, can someone help me?
Lots of thanks in advance.

Your script has several problems, the missing ti col is only one of them. (You can also use set key auto columnheader, then you must not give that option every time).
Don't use both y1 and y2 axis if you want to compare the values! Otherwise the correct bar heights are only a matter of luck...
Understand, how gnuplot positions the histogram bars, then you can exactly locate the top center of each bar. If you only use offset with char values (which is the case when you give only numbers), then your script will break as soon as you add or remove a data row.
The histogram clusters start at x-position 0, and are positioned centered at integer x values. Since you have two bars in each cluster and a gap of 1, the center of the first bar is at ($0 - 1/6.0) (= 1/(2 * (numberOfTorres + gapCount))), the second one at ($0 + 1/6.0):
set terminal pngcairo nocrop enhanced size 600,400 font ",8"
set output 'output.png'
set title 'Energía consumida por torre (MWh)' font ",20"
set boxwidth 0.8 absolute
set border 1
set style fill solid 1.00 border lt -1
set style histogram clustered gap 1 title textcolor lt -1
set style data histograms
set xtics border scale 1,0 nomirror autojustify norangelimit
unset ytics
set key off auto columnheader
set yrange [0:*]
set offset 0,0,graph 0.05,0
set linetype 1 lc rgb '#FF420E'
set linetype 2 lc rgb '#3465A4'
# dx = 1/(2 * (numberOfTorres + gap))
dx = 1/6.0
plot 'source.dat' using 2:xtic(1),\
'' u 3,\
'' u ($0 - dx):2:2 with labels,\
'' u ($0 + dx):3:3 with labels
Now, starting at the bars center you can safely use offset to specify only the offset relative to the bars top center:
plot 'source.dat' using 2:xtic(1),\
'' u 3,\
'' u ($0 - dx):2:2 with labels offset -1,1 ,\
'' u ($0 + dx):3:3 with labels offset 1,1
A second option would be to use the label's alignment: The labels of the red bars are right aligned at the bars right border, the labels of the blue bars are left aligned at the bars left border:
absoluteBoxwidth = 0.8
dx = 1/6.0 * (1 - absoluteBoxwidth)/2.0
plot 'source.dat' using 2:xtic(1),\
'' u 3,\
'' u ($0 - dx):2:2 with labels right offset 0,1 ,\
'' u ($0 + dx):3:3 with labels left offset 0,1
In any case, both options make your script more robust against changes of the input data.

This looks better :
plot fuente using 3:xtic(1) ls 1 ti col axis x1y1, '' u 3 ls 2 ti col axis x1y2, '' u ($0-1):3:3 with labels offset -3,1 , '' u ($0-1):2:2 with labels offset 3,1
You had 2 plots commands: only the first one was displayed.
Also, script.sh should be a bash script. This is a gnuplot script, so it should have another extension.

The problem is the ti col tab. You need to put it in every option, including labels and not only in bars. The right code is:
plot fuente using 2:xtic(1) ls 1 ti col, '' u 3 ls 2 ti col, '' u 0:2:2 ti col with labels offset -3,1 , '' u 0:3:3 ti col with labels offset 3,1
And that's how the picture is displayed now:
You can also avoid ti col and that is how it would look:

Related

How to display y-labels on top of histogram bars on gnuplot

I desgined a histogram in gnuplot however the y-scale needs to be in log2 due to huge difference in values. Therefore, to improve readability of the plot I pretend to display the concrete values on top of each bar. The values represent bytes and so I would like for this values also be in log2 and to be formated to display kb, Mb, ... as is being done in the y-axis.
How can I achieve this?
This is the comands I'm currently using:
set terminal postscript eps enhanced dash color "" 13
reset
set datafile separator ","
set title "Bytes per Protocol"
set xlabel "Protocol"
set ylabel "Bytes" rotate by 90
set yrange [0:1342177280]
set logscale y 2
set format y '%.0s%cB'
set style data histogram
set boxwidth 0.5
set style fill solid
set xtics format ""
set grid ytics
set style data histogram
set style histogram clustered gap 2
set grid ytics
set tic scale 0
set size 1,0.9
set size ratio 0.5
set key autotitle columnhead
set output "ex_a_1_BIG.eps"
plot "ex_a_1_BIG.csv" using ($3):xtic(1) title "IN", \
'' using ($5):xtic(1) title "OUT", \
'' using 0:($3):($3) with labels center offset -2,1 notitle, \
'' using 0:($5):($5) with labels center offset 2,1 notitle
This is the content of the csv I want to plot (I only want the bytes in and out):
protocol,packets in,bytes in,packets out,bytes out
ICMP,1833,141562,979,60334
IGMP,0,0,283,14006
TCP,158214,129221151,130101,47734355
UDP,68476,9571677,72530,24310734
Check help format_specifiers and help gprintf. And the example below.
What is a bit unfortunate, that in gnuplot apparently the prefix for 1 to 999 is a single space instead of an empty string.
For example, with the format '%.1s %cB' this leads to two spaces for 1-999 B and one space for the others, e.g. 1 kB. However, if you use '%.1s%cB' this leads to one space for 1-999 B and no space for the others e.g. 100kB. As far as I know, correct would be one space between the number and the units. I'm not sure whether there is an easy fix for this.
Code:
### prefixes
reset session
$Data <<EOD
1 1
2 12
3 123
4 1234
5 12345
6 123456
7 1234567
8 12345678
9 123456789
10 1234567890
11 12345678901
12 123456789012
13 1234567890123
EOD
set boxwidth 0.7
set style fill solid 1.0
set xtics 1
set yrange [0.5:8e13]
set multiplot layout 2,1
set logscale y # base of 10
set format y '%.0s %cB'
plot $Data u 1:2 w boxes lc rgb "green" notitle, \
'' u 1:2:(gprintf('%.1s %cB',$2)) w labels offset 0,1 not
set logscale y 2 # base of 2
set format y '%.0b %BB'
plot $Data u 1:2 w boxes lc rgb "red" notitle, \
'' u 1:2:(gprintf('%.1b %BB',$2)) w labels offset 0,1 not
unset multiplot
### end of code
Result:
Addition:
a workaround for number/unit space issue at least for the labels in the graph would be:
myFmt(c) = column(c)>=1 && column(c)<1000 ? \
gprintf('%.1s%cB',column(c)) : gprintf('%.1s %cB',column(c))
and
plot $Data u 1:2 w boxes lc rgb "green" notitle, \
'' u 1:2:(myFmt(2)) w labels offset 0,1 not
But for the ytics labels I still don't have an idea.

GNUPLOT - Can't display values over the bar

I'm trying make simple histogram with this file '.dat'
Moment "Energy consumed (MWh)"
"Apr-16" 2011.4
"May-16" 1869.6
"Jun-16" 1899.0
"Jul-16" 1659.0
"Aug-16" 1740.6
"Sep-16" 1670.0
For this purpose I have written the following script
#!/usr/bin/gnuplot
set term postscript
set terminal pngcairo nocrop enhanced size 700,700 font "arial,18"
set termoption dash
set output out
set boxwidth 0.5 absolute
set border 0
set style fill solid 1.00 border lt -1
set key off
set style histogram clustered gap 1 title textcolor lt -1
set datafile missing '-'
set style data histograms
set xtics border in scale 0,0 nomirror autojustify
set xtics norangelimit
set xtics ()
unset ytics
set title titulo
set yrange [0.0000 : limite] noreverse nowriteback
show style line
set style line 1 lt 1 lc rgb color lw 1
## Last datafile plotted: "immigration.dat"
plot fuente using (column(0)):2:xtic(1) title titulo ls 1 with boxes, '' using 0:2:2 with labels
In this case out is the output filename, titulo is the label that appears on the top of the image output, limite is the value that I use as biggest value on y-axi, and fuente is the source filename.
The result is this
I am trying display the values over the bar with some offset because I need the values over the bars and not inside the bars. I would need separate I am trying with code like:
plot fuente using (column(0)):2:xtic(1) title titulo ls 1 with boxes, '' using 0:($2 + 0.5):2 with labels
because I have seen many sites where they get it doing $2 + 0.5 but this it doesn't work for me.
What should I do? Please help me I am completly lost. Thanks in advance.
Use the offset parameter for the with labels plotting styles. With this you can add a vertical offset which you specify e.g. in character or graph units:
plot fuente using 0:2:xtic(1) with boxes, '' using 0:2:2 with labels offset 0, char 1
Sidenote: Adding the constant value of 0.5 to the y-value (like $2 + 0.5) doesn't work for you, because the 0.5 is in units of the y-axis, and very small compared to your yrange.

How to draw a histogram with broken x-axis and string labels?

I am trying to draw a histogram with broken x-axis. I learnt the basic solution from this post.
However, the x-axis of my histogram is based on strings, not number. It's like this:
set terminal pdf
set output "test-bar.pdf"
set boxwidth 1.0 absolute
set style fill solid 1 border 0
set datafile separator ','
set style data histograms
set xtics nomirror rotate by -45
set ylabel 'Normalized Overhead (%)'
set grid ytics
set yrange [0:10]
plot 'test-bar.csv' using 2:xtic(1) lc rgb "#1E90FF" title ''
And the data is listed like this:
expand , 8.63390441828
cut , 6.84657194596
sync , 6.03615235627
fold , 4.22117995557
nl , 3.54228486647
truncate , 2.66222961714
tr , 2.38357169059
stty , 2.28166797757
users , 2.04211869831
factor , 1.81517270821
tac , 1.790947574
uniq , 1.78799489138
mv , 1.75054704603
mktemp , 1.72228202368
dircolors , 1.6974169738
Right now the plot is in this way:
If I want to leverage the broken axis feature, say, insert the broken between stty and users, how can I do that?
Am I clear enough? Thanks.
Although you use xtic labels from your data file, the xtics are placed at integer x-values, starting at 0. Now, you cannot directly set arbitrary x-values when plotting histograms. You must use newhistogram at ... to shift the second part of the histogram further to the right:
split = 8
plot 'test-bar.csv' using 2:xtic(1) every ::0::(split-1) lt 1,\
newhistogram at split+1,\
'' using 2:xtic(1) every ::split lt 1
Drawing of the upper and lower borders as well as the broken axis signs is done as shown in the post you linked. A possible full script could be
set terminal pdf
set output "test-bar.pdf"
set boxwidth 0.5 absolute
set style fill solid 1 border 0
set datafile separator ','
set style data histograms
set style histogram rowstacked
set xtics nomirror rotate by -45
set ylabel 'Normalized Overhead (%)'
set grid ytics
set yrange [0:10]
unset key
set border 2+8
set linetype 1 lc rgb "#1E90FF"
split=8
dx = 0.125
dy = 0.03
do for [i=0:1] {
set arrow 1+i from graph 0,graph i to first split-dx,graph i lt -1 nohead
set arrow 3+i from first split+dx,graph i to graph 1,graph i lt -1 nohead
set arrow 5+i from first split-2*dx,graph i-dy to first split,graph i+dy lt -1 nohead
set arrow 7+i from first split,graph i-dy to split+2*dx,graph i+dy lt -1 nohead
}
plot 'test-bar.csv' using 2:xtic(1) every ::0::(split-1) lt 1,\
newhistogram at split+1,\
'' using 2:xtic(1) every ::split lt 1
Alternatively, if you don't add or stack more columns, you could use the boxes plotting style, which allows you to use a normal numerical axis.

Add a single point at an existing plot

I am using the following script to fit a function on a plot. In the output plot I would like to add a single value with etiquette on the fitting curve lets say the point f(3.25). I have read that for gnuplot is very tricky to add one single point on a plot particularly when this plot is a fitting function plot.
Has someone has an idea how to add this single point on the existing plot?
set xlabel "1000/T (K^-^1)" font "Helvetica,20"
#set ylabel "-log(tau_c)" font "Helvetica,20"
set ylabel "-log{/Symbol t}_c (ns)" font "Helvetica,20"
set title "$system $type $method" font "Helvetica,24"
set xtics font "Helvetica Bold, 18"
set ytics font "Helvetica Bold, 18"
#set xrange[0:4]
set border linewidth 3
set xtic auto # set xtics automatically
set ytic auto # set ytics automatically
#set key on bottom box lw 3 width 8 height .5 spacing 4 font "Helvetica, 24"
set key box lw 3 width 4 height .5 spacing 4 font "Helvetica, 24"
set yrange[-5:]
set xrange[1.5:8]
f(x)=A+B*x/(1000-C*x)
A=1 ;B=-227 ; C=245
fit f(x) "$plot1" u (1000/\$1):(-log10(\$2)) via A,B,C
plot [1.5:8] f(x) ti "VFT" lw 4, "$plot1" u (1000/\$1):(-log10(\$2)) ti "$system $type" lw 10
#set key on bottom box lw 3 width 8 height .5 spacing 4 font "Helvetica, 24"
set terminal postscript eps color dl 2 lw 1 enhanced # font "Helvetica,20"
set output "KWW.eps"
replot
There are several possiblities to set a point/dot:
1. set object
If you have simple points, like a circle, circle wedge or a square, you can use set object, which must be define before the respective plot command:
set object circle at first -5,5 radius char 0.5 \
fillstyle empty border lc rgb '#aa1100' lw 2
set object circle at graph 0.5,0.9 radius char 1 arc [0:-90] \
fillcolor rgb 'red' fillstyle solid noborder
set object rectangle at screen 0.6, 0.2 size char 1, char 0.6 \
fillcolor rgb 'blue' fillstyle solid border lt 2 lw 2
plot x
To add a label, you need to use set label.
This may be cumbersome, but has the advantage that you can use different line and fill colors, and you can use different coordinate systems (first, graph, screen etc).
The result with 4.6.4 is:
2. Set an empty label with point option
The set label command has a point option, which can be used to set a point using the existing point types at a certain coordinate:
set label at xPos, yPos, zPos "" point pointtype 7 pointsize 2
3. plot with '+'
The last possibility is to use the special filename +, which generates a set of coordinates, which are then filtered, and plotted using the labels plotting style (or points if no label is requested:
f(x) = x**2
x1 = 2
set xrange[-5:5]
set style line 1 pointtype 7 linecolor rgb '#22aa22' pointsize 2
plot f(x), \
'+' using ($0 == 0 ? x1 : NaN):(f(x1)):(sprintf('f(%.1f)', x1)) \
with labels offset char 1,-0.2 left textcolor rgb 'blue' \
point linestyle 1 notitle
$0, or equivalently column(0), is the coordinate index. In the using statement only the first one is taken as valid, all other ones are skipped (using NaN).
Note, that using + requires setting a fixed xrange.
This has the advantages (or disadvantages?):
You can use the usual pointtype.
You can only use the axis values as coordinates (like first or second for the objects above).
It may become more difficult to place different point types.
It is more involved using different border and fill colors.
The result is:
Adding to Christoph's excellent answers :
4. use stdin to pipe in the one point
replot "-" using 1:(f($1))
2.0
e
and use the method in 3rd answer to label it.
5. bake a named datablock
(version > 5.0) that contains the one point, then you can replot without resupplying it every time:
$point << EOD
2.0
EOD
replot $point using 1:(f($1)):(sprintf("%.2f",f($1))) with labels
6. A solution using a dummy array of length one:
array point[1]
pl [-5:5] x**2, point us (2):(3) pt 7 lc 3
7. Or through a shell command (see help piped-data):
pl [-5:5] x**2, "<echo e" us (2):(3) pt 7 lc 3
pl [-5:5] x**2, "<echo 2 3" pt 7 lc 3
8. Special filename '+'
pl [-5:5] x**2, "+" us (2):(3) pt 7 lc 3
It seems to be the shortest solution. But note that while it looks like a single point, these are like 500 points (see show samples) plotted on the same position.
To have only one point the sampling needs to be temporarily adjusted (see help plot sampling)
pl [-5:5] x**2, [0:0:1] "+" us (2):(3) pt 7 lc 3
9. Function with zero sampling range length
Shortest to type, but plotting as many points on top of each other as many specified with samples
pl [-5:5] x**2, [2:2] 3 w p pt 7 lc 3

gnuplot histogram does not visualize small numbers

I'm just taking the first look at gnuplot today and using the histogram example, I wanted to build a small example as from the tutorial, only I changed the input numbers from 50,000 something to 100-range and it is not visualized correctly.
Here's the dat file
Region Denmark Netherlands Norway Sweden
1891-1900 500 400 300 200
And this is the gnuplot script
set terminal pngcairo
set output 'histograms.2.png'
set boxwidth 0.9 absolute
set style fill solid 1.00 border lt -1
set key inside right top vertical Right noreverse noenhanced autotitles nobox
set style histogram clustered gap 5 title offset character 0, 0, 0
set datafile missing '-'
set style data histograms
set xtics border in scale 0,0 nomirror rotate by -45 offset character 0, 0, 0
set xtics norangelimit font ",8"
set xtics ()
set title "US immigration from Northern Europe\n(same plot with larger gap between clusters)"
set yrange [ 0.00000 : 3000. ] noreverse nowriteback
i = 22
plot 'immigration.dat' using 1:xtic(1) ti col, '' u 2 ti col, '' u 3 ti col, '' u 4 ti col
As seen in here:
the first column is wrongly visualized. any ideas?!
I think you want:
plot 'immigration.dat' using 2:xtic(1) ti col, '' u 3 ti col, '' u 4 ti col, '' u 5 ti col
In your version, gnuplot is interpreting the data in the first column (1891-1900) as a number (1891). You can also see this by carefully looking at the key -- The red bar corresponds to Region.

Resources