When Googling "horizontal gnuplot bar chart", the first result I could find http://www.phyast.pitt.edu/~zov1/gnuplot/html/histogram.html suggests rotating (!) the final bar chart which seems rather baroque. Nonetheless I tried the approach but the labels are cut off.
reset
$heights << EOD
dad 181
mom 170
son 100
daughter 60
EOD
set yrange [0:*] # start at zero, find max from the data
set boxwidth 0.5 # use a fixed width for boxes
unset key # turn off all titles
set style fill solid # solid color boxes
set colors podo
set xtic rotate by 90 scale 0
unset ytics
set y2tics rotate by 90
plot '$heights' using 0:2:($0+1):xtic(1) with boxes lc variable
Is there a better approach?
The link you are referring to is from approx. 2009. gnuplot has developed since then. As #Christoph suggested, check help boxxyerror.
Script: (edit: shortened by using 4-columns syntax for boxxyerror, i.e. x:y:+/-dx:+/-dy)
### horizontal bar graph
reset session
$Data << EOD
dad 181
mom 170
son 100
daughter 60
EOD
set yrange [0:*] # start at zero, find max from the data
set style fill solid # solid color boxes
unset key # turn off all titles
myBoxWidth = 0.8
set offsets 0,0,0.5-myBoxWidth/2.,0.5
plot $Data using (0.5*$2):0:(0.5*$2):(myBoxWidth/2.):($0+1):ytic(1) with boxxy lc var
### end of script
Result:
Addition:
what does
2:0:(0):2:($0-myBoxWidth/2.):($0+myBoxWidth/2.):($0+1):ytic(1) mean?
Well, it looks more complicated than it is. Check help boxxyerror. From the manual:
6 columns: x y xlow xhigh ylow yhigh
So, altogether:
x take value from column 2, but not so relevant here since we will use the xyerror box
y take pseudocolumn 0 which is line number starting from zero, check help pseudocolumns, but not so relevant here as well
xlow (0) means fixed value of zero
xhigh value from column 2
ylow ($0-myBoxWidth/2.), line number minus half of the boxwidth
yhigh ($0+myBoxWidth/2.), line number plus half of the boxwidth
($0+1) together with ... lc var: color depending on line number starting from 1
ytic(1): column 1 as ytic label
For some reason (which I don't know) gnuplot still doesn't seem to have a convenient horizontal histogram plotting style, but at least it offers this boxxyerror workaround.
Related
I would like to create a histogram with boxes using three pieces of data, first the number of iterations as the x-axis, then the execution time as the y-axis and finally the number of processes used.
I would like to see a bar for each number of processes used, and with a color specific to the value of the number of processes. How can I do this?
My test data is defined as:
"iterations" "processes" "time_execution"
1000 1 14
1000 2 10
1000 4 9
4000 1 60
4000 2 42
4000 4 45
7000 1 80
7000 2 70
7000 4 50
And here is my script so far, but I can't get it to place the three bars side by side:
set term svg
set output out.svg
set boxwidth 1
set style fill solid 1.00 border 0
set style histogram
set size ratio 0.8
set xlabel 'Number of iterations'
set ylabel offset 2 'Time execution in seconds'
set key left Right
set key samplen 2 spacing .8 height 3 font ',10'
set title 'Time execution per iterations and processus used'
plot test.data u 1:3:2 w boxes
Thanks!
I guess your data format doesn't fit the expected histogram format. Check the examples on the gnuplot homepage, although, I think the examples are too crowded which might be confusing and maybe the reason why there are so many histogram questions on SO.
If you modify your data format (see below) it will be easy to plot the histogram.
You can probably use any format, but the effort to prepare the data will be higher (see for example here: Gnuplot: How to plot a bar graph from flattened tables).
Script:
### plotting histogram requires suitable input data format
reset session
$Data <<EOD
xxx 1 2 4
1000 14 10 9
4000 60 42 45
7000 80 70 50
EOD
set style histogram clustered gap 1
set style data histogram
set boxwidth 0.8 relative
set style fill solid 0.3
set xlabel 'Number of iterations'
set xtics out
set ylabel 'Time execution in seconds'
set grid x,y
set key top center title "Processors"
set offset 0,0,0.5,0
plot for [col=2:4] $Data u col:xtic(1) ti col
### end of script
Result:
You can use lc variable
plot test.data u 1:3:2 w boxes lc variable notitle
EDIT
notitle is not necessary, but it makes the plot seems better.
I try to generate a histogram plot with gnuplot. I have positive and negative values. Positive values go to the top of the chart, but negative values go to the bottom of the chart..
I would like to change the base for go up and go down
from 0 to -100 for example.
Maybe, it's not the good type of graphic to do that ?
I have tried this :
gnuplot -e "set terminal png size 20000, 1500; set yrange [-100:*]; set title 'VU meter 0'; set style data histogram; set style histogram clustered gap 1; set style fill solid 1 noborder; plot 'testVUmeter0.tsv' using 2:xticlabels(1)" > out.png
Thanks
As far as I know the plotting styles histogram and with boxes always start at y=0.
Assuming I understood your question correctly, you want to shift this zero level e.g. to -100.
As long as you do not need an advanced histogram style but just simple boxes, one possible solution could be to use the plotting style with boxxyerror. Compared to #meuh's solution, here, gnuplot automatically takes care about the y-tics.
Code:
### shift zero for boxes
reset session
$Data <<EOD
A -20
B -140
C 100
D -340
E +250
F 0
EOD
myOffset = -100
myWidth = 0.8
set style fill solid 1.0
set arrow 1 from graph 0, first myOffset to graph 1, first myOffset nohead ls -1
set style textbox opaque
plot $Data u 0:2:($0-myWidth/2.):($0+myWidth/2.):(myOffset):2:xtic(1) w boxxyerror notitle, \
'' u 0:2:2 w labels boxed notitle
### end of code
Result:
You can calculate a new y value at each point, taking into account some wanted offset. For example, setting bot=-20 to give a bottom y value of -20 you can refer to ($2-bot) to convert, say, -5 to -5-(-20)=15` above 0.
set terminal png size 400,300
set output "out.png"
set style data histogram
set style histogram clustered gap 1
set style fill solid 1 noborder
bot=-20
set yrange [0:*]
set ytics ("-10" -10-bot, "0" 0-bot, "10" 10-bot, "20" 20-bot, "30" 30-bot)
plot "data" using (($2)-bot):xticlabels(1) notitle, \
"" using 0:($2+3-bot):(sprintf("%d",$2)) with labels notitle
with data of
1 33
2 44
3 22
4 -12
gives the plot:
Suppose I have the following data:
"1,5"
"2,10"
""
"3,4"
"4,2"
""
"5,6"
"6,10"
I want to graph this using gnuplot with a line between each condition, similar to this display:
How might this be accomplished? I have looked into gridlines, but that does not seem to suit my need. I am also looking for a solution that will automatically draw condition / phase lines between each break in the data set.
As mentioned in the comments and explained in the linked question and its answers, you can draw arbitrary lines manually via set arrow ... (check help arrow).
However, if possible I don't want to adjust the lines manually every time I change the data or if I have many different plots.
But, hey, you are using gnuplot, so, make it automated!
To be honest, within the time figuring out how it can be done I could have changed a "few" lines and labels manually ;-). But now, this might be helpful for others.
The script below is written in such a way that it doesn't matter whether you have zero, one or two or more empty lines between the different blocks.
Comments:
the function valid(1) returns 0 and 1 if column(1) contains a valid number (check help valid).
the vertical lines are plotted with vectors (check help vectors). The x-position is taken as average of the x-value before the label line and the x-value after the label line. The y-value LevelY is determined beforehand via stats (check help stats).
the labels are plotted with labels (check help labels) and positioned at the first x-value after each label line and at an y-value of LevelY with an offset.
Script:
### automatic vertical lines and labels
reset session
$Data <<EOD
Baseline
1 10.0
2 12.0
3 10.5
4 11.0 # zero empty lines follow
Treatment
5 45.0
6 35.0
7 32.5
8 31.0 # one empty line follows
Baseline
9 14.0
10 12.8
11 12.0
12 11.3 # two empty lines follow
Treatment
13 35.0
14 45.0
15 45.0
16 37.0
EOD
set offset 1,1,1,1
set border 3
set title "Student Performance" font ",14"
set xlabel "Sessions"
set xtics 1 out nomirror
set ylabel "Number of Responses"
set yrange [0:]
set ytics out nomirror
set key noautotitle
set grid x,y
stats $Data u 2 nooutput
LevelY = STATS_max # get the max y-level
getLinePosX(col) = (v0=v1,(v1=valid(col))?(x0=x1,x1=column(1)):0, v0==0?(x0+x1)/2:NaN)
getLabel(col) = (v0=v1,(v1=valid(col))?0:(h1=strcol(1),h0=h1),column(1))
plot x1=NaN $Data u (y0=(valid(1)?$2:NaN),$1):(y0) w lp pt 13 ps 2 lw 2 lc "red", \
x1=v1=NaN '' u (getLinePosX(1)):(0):(0):(LevelY) w vec nohead lc "black" lw 1.5 dt 2, \
v1=NaN '' u (getLabel(1)):(LevelY):(sprintf("%s",v0==0?h0:'')) w labels left offset 0,1.5 font ",12"
### end of script
Result:
I need to be able to position the tic marks so that they are between the bars in the graph.
That way it can be read that there were 2 points between 0 and 14, 0 between 15 and 30, and so on, instead of the tics centered underneath the bars. Is there any way to automatically do that based on the box width?
Here is my current script attempt:
set xtics out nomirror
set ytics out nomirror
set tic scale 0
set style fill solid 1.00 border 0
set offset graph 0.1, 0.05, 0.1, 0.0
set boxwidth 15 *.9
set xtics offset -(15 *.9)/2
set term png
set output "graph.png"
plot 'data.dat' using 1:2:xtic(1) with boxes
Here is the .dat:
0 2
15 0
30 0
45 0
60 1
75 1
90 33
EDIT
It appears that the following works consistently, based on the boxwidth:
set bwidth=15*.9
set boxwidth bwidth
set xtics out nomirror offset -bwidth/2 left
There still might be a better way.
With your solution you only shift the tic labels. I would also shift the tics.
Here is my solutions:
set tics out nomirror
set style fill solid 1.00 noborder
set autoscale fix
set offset 5,5,5,0
# extract the first and second x-values
stats 'data.dat' using 1 every ::::1 nooutput
start = STATS_min
width = STATS_max - STATS_min
set boxwidth width *.9
set xtics start, width
set term pngcairo
set output "graph.png"
plot 'data.dat' using ($1+width/2.0):2 with boxes
The first and second data values are extracted automatically (requires version >= 4.6.0). These values are used to
Set the boxwidth
Set the xtics (start value and increment)
Shift the data points by half of the x-value increment.
See e.g. Gnuplot: How to load and display single numeric value from data file for another example for extracting data with the stats command. Instead of loading the data with stats you could of course also use
start = 0
width = 15
The result with 4.6.3 is:
When running the following script, I get an error message:
set terminal postscript enhanced color
set output '| ps2pdf - histogram_categorie.pdf'
set auto x
set key off
set yrange [0:20]
set style fill solid border -1
set boxwidth 5
unset border
unset ytic
set xtics nomirror
plot "categorie.dat" using 1:2 ti col with boxes
The error message that I get is
smeik:plots nvcleemp$ gnuplot categorie.gnuplot
plot "categorie.dat" using 1:2 ti col with boxes
^
"categorie.gnuplot", line 13: x range is invalid
The content of the file categorie.dat is
categorie aantal
poussin 13
pupil 9
miniem 15
cadet 15
junior 6
senior 5
veteraan 8
I understand that the problem is that I haven't defined an x range. How can I make him use the first column as values for the x range? Or do I need to take the row numbers as x range and let him use the first column as labels? I'm using Gnuplot 4.4.
I'm ultimately trying to get a plot that looks the same as the plot I made before this one. That one worked fine, but had numerical data on the x axis.
set terminal postscript enhanced color
set output '| ps2pdf - histogram_geboorte.pdf'
set auto x
set key off
set yrange [0:40]
set xrange [1935:2005]
set style fill solid border -1
set boxwidth 5
unset border
unset ytic
set xtics nomirror
plot "geboorte.dat" using 1:2 ti col with boxes,\
"geboorte.dat" using 1:($2+2):2 with labels
and the content of the file geboorte.dat is
decennium aantal
1940 2
1950 1
1960 3
1970 2
1980 3
1990 29
2000 30
the boxes style expects that the x-values are numeric. That's an easy one, we can give it the pseudo-column 0 which is essentially the script's line number:
plot "categorie.dat" using (column(0)):2 ti col with boxes
Now you probably want the information in the first column on the plot somehow. I'll assume you want those strings to become the x-tics:
plot "categorie.dat" using (column(0)):2:xtic(1) ti col with boxes
*careful here, this might not work with your current boxwidth settings. You might want to consider set boxwidth 1 or plot ... with (5*column(0)):2:xtic(1) ....
EDIT -- Taking your datafiles posted above, I've tested both of the above changes to get the boxwidth correct, and both seemed to work.