I am plotting a histogram rowstacked very similar to this graph (the last one on this page) :
What I would like to do is to have different colors for each year bin. This colors would repeat from a newhistogram to another. I have not yet found a way to do this.
An example with my data of what I am trying to accomplish is
Thank you for your help.
So what is your actual problem with this? Using the histograms plotting should work fine. Consider the following data file
A -1 1 -0.5 0.5
B -2 2 -1 1
C -3 3 -1.5 1.5
D -4 4 -2 2
E -5 5 -2.5 2.5
F -4 4 -2 2
G -3 3 -1.5 1.5
which you can plot with
set key tmargin horizontal
set style fill solid noborder
set style data histograms
set style histogram gap 1
plot 'data.dat' using 2:xtic(1) title "First",\
'' using 4 title "Second",\
newhistogram at 0,\
'' using 3 title "Third",\
'' using 5 title "Fourth"
The result is
Here, I explicitely assume, that in one column you have only negative or only positive values. But that isn't necessary in general. All further fine-tuning depends on your actual data file format, and other, unknown, conditions.
Related
I am a beginner in gnuplot. Recently I tried to visualize a pressure field on adaptive mesh.
Firstly I got the coordinates of nodes and center of the cell and the pressure value at the center of the cell.
And, I found something difficult to deal with. That is the coordinates in x and y directions are not regular, which made me feel hard in preparing the format of source data. For regular and equal rectangular case, I can do something just like x-y-z format. But is there any successful case in adaptive mesh?
I understand that you have some x,y,z data which is in no regular grid (well, your adaptive mesh).
I'm not fully sure whether this is what you are looking for, but
gnuplot can grid the data for you, i.e. inter-/extrapolating your data within a regular grid and then plot it.
Check help dgrid3d.
Code:
### grid data
reset session
# create some test data
set print $Data
do for [i=1:200] {
x = rand(0)*100-50
y = rand(0)*100-50
z = sin(x/15)*sin(y/15)
print sprintf("%g %g %g",x,y,z)
}
set print
set view equal xyz
set view map
set multiplot layout 1,2
set title "Original data with no regular grid"
unset dgrid3d
splot $Data u 1:2:3 w p pt 7 lc palette notitle
set title "Gridded data"
set dgrid3d 100,100 qnorm 2
splot $Data u 1:2:3 w pm3d
unset multiplot
### end of code
Result:
If you have the size of each cell, you can use the "boxxyerror" plotting style. Let xdelta and ydelta be half the size of a cell along the x-axis and y-axis.
Script:
$datablock <<EOD
# x y xdelta ydelta pressure
1 1 1 1 0
3 1 1 1 1
1 3 1 1 1
3 3 1 1 3
2 6 2 2 4
6 2 2 2 4
6 6 2 2 5
4 12 4 4 6
12 4 4 4 6
12 12 4 4 7
EOD
set xrange [-2:18]
set yrange [-2:18]
set palette maxcolors 14
set style fill solid 1 border lc black
plot $datablock using 1:2:3:4:5 with boxxyerror fc palette title "mesh", \
$datablock using 1:2 with points pt 7 lc rgb "gray30" title "point"
pause -1
In this script, 5-column data (x, y, xdelta, ydelta, pressure) is given for "boxxyerror" plot. To colorize the cells, the option "fc palette" is required.
Result:
I hope this figure is what you are looking for.
Thanks.
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 am trying to plot a bar chart/histogram that shows, for every point of the x axis, two bars, each of which is divided in three parts. Take the following dataset:
Min # Max # Avg # Min % Max % Avg %
6 12 6.67 13 100 35.25
0 6 3 0 90 43.25
235 1243 553 66.67 100 83.43
The idea is that for each row, there will be a pair of vertical bars, with the left one representing the three # values and the right one representing the three % values. The values are made-up, but the scale is more or less the real one.
So far, I have managed to get the following script, which is a frankenstein of several online scripts I found:
set ytics 10 nomirror tc lt 1
set y2tics 100 nomirror tc lt 2
set yrange [0:120]
set y2range [0:1500]
set style fill solid border -1
plot "table2.dat" using 5:xticlabels(1) with boxes lt rgb "#40FF00" t "Max \%",\
"" using 6 lt rgb "#406090" t "Avg \%",\
"" using 4 with boxes lt rgb "#403090" t "Min \%"
This will plot out the following chart:
What I cannot seem to figure out is how to put the second bar for the first three columns. Ideally, that "X" would also be replaced by a dotted line cutting the bar. The reason for the two Y axes is that each bar follows a different scale, so the second bar would have to be proportional to the right-side y axis. Finally, I had to add that little "hack" of making yrange higher than 100 so that the bars would not "hit the top". If there is another way to do that, that'd be great.
Thanks in advance for any help that can be given, I am a complete newbie at gnuplot but since trying to make this chart using spreadsheet tools was an even bigger pain, I am hopeful that someone'll be able to help with at least some of those problems.
Edit.: I will take suggestions for a better title for this question.
You can get a little further by setting a boxwidth to 0.4 of the default width, and defining a function (I used f here) that converts your data in columns 1 to 3 into percentage values too, and explicitly providing an x coordinate with the syntax x:y and using $1 to refer to column 1 etc. $0 is the row.
set boxwidth 0.4 relative
f(y,max) = (y*100./max)
plot "table2.dat" \
using 5:xticlabels(1) with boxes lt rgb "#40FF00" t "Max \%",\
"" using 6 lt rgb "#406090" t "Avg \%",\
"" using 4 with boxes lt rgb "#403090" t "Min \%",\
"" using ($0-.5):(f($2,$2)) with boxes lt rgb "red" t "Max",\
"" using ($0-.5):(f($3,$2)) lt rgb "blue" t "Avg",\
"" using ($0-.5):(f($1,$2)) with boxes lt rgb "orange" t "Min"
I used some garish colours to show the new boxes:
I have crawled many similar questions without finding the proper problem/question/answer...
I want to use gnuplot to make a histogram plot out of a distributed data file with bars/boxes of equal width and intervals. So I need to count/integrate over the width(=1) of my bars. That's why I wanted to use the 'smooth frequency' command:
#gnuplot
bin(x)=floor(x+0.5)
set boxwidth 0.8 relative
set style fill pattern
set grid
set xrange [0:11]
set yrange [0:3]
set xtics in 0,2,10
set mxtics 2
set ytics 0,1,3
set mytics 1
p 'data.dat' u (bin($1)):(1) smooth freq w boxes
#data.dat
2.489
7.5
9.128
9.567
I tried it and the result was the same, as with my handmade file plotted with boxes:
#gnuplot2
[...]
p 'data2.dat' w boxes
#data2.dat
2 1
8 1
9 1
10 1
Smooth frequency seems to do its job properly, but the result is not what I intended to do...: Image
Then I figured out, what the problem is. It is solved using my handmade data3.dat:
#gnuplot
p 'data3.dat' w boxes
#data3.dat
1 0
2 1
3 0
4 0
5 0
6 0
7 0
8 1
9 1
10 1
Image
So the problems are the holes in my data range, that aren't counted as '0'. With these holes, gnuplot seems to adjust the box width by itself to fit in the whole space left. How can I prevent this to get my desired result?
I think the problem is the relative key. Try:
set boxwidth 0.8 absolute
How can I do this in gnuplot:
plot "test.csv" using 1:2 if value_in_column_3 == 80.0
It should only select those rows where column 3 == 80.0 and ignore all other rows (It should not plot a 0 for the other rows, simply ignore them)
Thanks in advance.
Consider the following dataset (1.dat),
1 0.8 0
2 0.6 0
3 0.9 1
4 1.1 0
5 0.7 0
6 0.6 1
where we want to plot the first two columns only when the third one equals zero. Then you can try this:
plot '1.dat' using 1:($3==0?$2:1/0)
(Credit to markjoe on Gnuplot mailing-list.)
Case where one wants to plot conditionally on another column containing text:
data
1 0.8 a
2 0.6 a
3 0.9 a
1 2.1 b
2 1.7 b
3 1.6 b
code
set terminal postscript color
set xrange [0:4]
set yrange [0:3]
plot "1.dat" using 1:(stringcolumn(3) eq "a"? $2:1/0) title "a" lc rgb "blue" ,\
"" using 1:(stringcolumn(3) eq "b"? $2:1/0) title "b" lc rgb "red"
command
gnuplot < 1.par > 1.ps
As chl says above, the only way to do this in gnuplot is rather hacky: you have to use gnuplot's terniary ?: operator to generate a numerical error on the points you want to filter out of your dataset.
I may be biased here as I'm an author on the project, but you may want to have a look at Pyxplot http://www.pyxplot.org.uk (also free and open source), written by a group of gnuplot users who were a bit fed up with hacky syntax like this.
Its syntax is very similar to gnuplot, but with extensions. For what you want, you can specify a "select criterion" in the plot command, and points are only included if it tests True. See http://pyxplot.org.uk/current/doc/html/sec-select_modifier.html for more information.
Another hack would be to use a shell command like awk:
plot "< awk '$3==80.0 { print $1, $2 }' test.csv" using 1:2
If you are calling a script, use column(2) instead of $2
plot "1.dat" using 1:(stringcolumn(3) eq "a"? column(2):1/0) title "a" lc rgb "blue" ,\
"" using 1:(stringcolumn(3) eq "b"? column(2):1/0) title "b" lc rgb "red"