I'm new in gnuplot and sorry that my problem formulation might be unprecise, but I don't know how to find the tools/commnds needed to solve my problem. The code for plotting I would like to integrate in my bash file.
I have a data set like:
285 1 50 7.35092
265 1 50 7.35092
259 1 50 7.35092
258 1 50 7.35092
264 1 50 7.35092
491 5 50 33.97
488 5 50 33.97
495 5 50 33.97
492 5 50 25.1649
495 5 50 33.0725
500 5 50 13.6176
507 5 50 32.2502
489 5 50 33.0725
494 5 50 33.97
491 5 50 33.97
746 10 50 34.6007
746 10 50 34.6007
767 10 50 30.858
745 10 50 34.8789
746 10 50 34.6007
747 10 50 34.6007
758 10 50 34.6007
772 10 50 34.60
I already grouped the data by entering a new line between blocks. I would like to calculate for each block the mean and standard deviation of the 4th column.
Then I would like to plot on the Y axes the mean with the confidence interval (standard deviation) and on the X axes the value from the second column.
Each data block has a unique number in the 2nd column.
Solution: so far I got the values for a point from the first block but while I try to plot I get an error:
#myBash code for plotting.sh
FILEIN=simulationR.txt
rm plotTestR.png
gnuplot << EOF
reset
set terminal png
set output 'plotTestR.png'
set ylabel 'reward'
set xlabel 'Nr of simualtion'
set title 'Simualtio duration'
set grid
stats "$FILEIN" using 4 every :::0::0 nooutput
mean1 = sprintf('%.3f', STATS_mean)
std1 = sprintf('%.3f', STATS_stddev)
stats "$FILEIN" using 2 every :::0::0 nooutput
x1 = sprintf('%.3f', STATS_max)
plot '-' w yerrorbars title std1
x1 mean1 std1
exit
EOF
and the error:
gnuplot> plot '-' w yerrorbars title std1
^
line 1: Bad data on line 1 of file -
Usually, gnuplot isn't made for such data processing tasks. That's best done with an external script, which does the processing and writes to stdout, which can then be feed directly to gnuplot like
plot '< python myscript.py simulationR.txt'
In your example, you can only have fixed data after the plot '-' part, no variable substitution is done here.
However, gnuplot version 5 introduces a new inline data structure, to which you can write your computed values (set print $data).
Note, that the following is a plain gnuplot script, if you want to wrap it in a bash script (which is not necessary, since you can pass variables to a gnuplot script via the command line), then you must escape the $ characters.
FILEIN="simulationR.txt"
system('rm -f plotTestR.png')
reset
set terminal pngcairo
set output 'plotTestR.png'
set ylabel 'reward'
set xlabel 'Nr of simulation'
set title 'Simulation duration'
set grid
set print $data
do for [i=0:2] {
stats FILEIN using 2:4 every :::i::i nooutput
print sprintf("%e %e %e", STATS_max_x, STATS_mean_y, STATS_stddev_y)
}
set autoscale xfix
set offsets 1,1,0,0
plot $data using 1:2:3 w yerrorbars
A further improvement could be to separate two blocks by two blank lines, in which case you can use
stats 'simulationR.txt' using 0 nooutput
to have the number of blocks in the variable STATS_blocks, and you can rewrite the loop as
do for [i=0:STATS_blocks-1] {
stats FILEIN using 2:4 index i nooutput
print sprintf("%e %e %e", STATS_max_x, STATS_mean_y, STATS_stddev_y)
}
Related
I have a data file with 10 lines with 1000 values each line and I'm trying to plot this values with this script
#!/usr/bin/gnuplot -persist
plot "data.dat" using [1:1000] title "" with lines
but I get this error
plot "data.dat" using [1:1000] title "" with lines
^
"./plot.sh", line 3: invalid expression
How can I indiate a interval form the first value to the 1000 value?I't posible to set a diferent random clor to every line?
As #vaettchen pointed out, gnuplot wants data in columns and plotting rows is not straightforward. So, best would be if your data was transposed. Unfortunately, gnuplot has no function to transpose data. So, you have to use external tools to transpose your data.
Although, if your data is 10 lines with 1000 values each, i.e. a strict 10x1000 matrix, you could do something with gnuplot only (see below).
However, if your data is not a strict matrix, e.g. one line has more or less values or one value missing the method below won't work.
The following example (just 5 lines with 7 values each) illustrates plotting columns and plotting rows.
### plotting columns and rows
reset session
set colorsequence classic
$Data <<EOD
11 12 13 14 15 16 17
21 22 23 24 25 26 27
31 32 33 34 35 36 37
41 42 43 44 45 46 47
51 52 53 54 55 56 57
EOD
# get the number of rows
stats $Data u 0 nooutput
RowCount = STATS_records
# do the plot
set multiplot layout 1,2
set title "Plotting columns"
set xlabel "Row no."
set xtics 1
# plot all columns from 1 to *(=autodetection)
plot for [i=1:*] $Data u ($0+1):i w lp pt 7 not
set title "Plotting rows"
set xlabel "Column no."
# plot all rows
plot for [i=0:RowCount-1] $Data matrix u ($1+1):0 every :::i::i w lp pt 7 not
unset multiplot
### end of code
Which results in:
There is a style to fill the space between two functions of x.
Examples of such plots can be found e.g. at http://gnuplot.sourceforge.net/demo/fillbetween.html
Is there any way to make similar plot, but with flipped x and y axes?
Here is the desired shape of a curve (without rotated/mirrored labels, titles and legends, of course)...
It could be done with closed contour (like last example here http://www.gnuplot.info/demo_svg_cvs/fillcrvs.html), but this would require reshuffling the data file. Any other options?
Thank you!
You can't do this directly. From help filledcurves:
The third variant fills the area between two curves sampled at the same set of
x coordinates. It requires three columns of input data (x, y1, y2).
I don't think you can specify (y, x1, x2) directly. As a workaround you can the area between the y axis and the larger function in some color, and then fill the area between the y axis and the smaller function in white:
x1(y) = cos(y)+1
x2(y) = cos(y)+2
xmax(y) = (x1(y) > x2(y) ? x1(y) : x2(y))
xmin(y) = (x1(y) < x2(y) ? x1(y) : x2(y))
plot '+' using (xmax($1)):1 with filledcurve y1, \
'+' using (xmin($1)):1 with filledcurve y1 fillcolor rgb "white"
This probably has to be tweaked a little if one or both of the two functions can be negative.
With gnuplot >=5.2 it could be tweaked even further because it allows arrays.
The following code shows a workaround how filled curves between vertically oriented curves can be realized. You can even use transparency. If you download the attached PNG you will notice that it actually has a transparent background. The basic idea behind this workaround is to make closed areas and fill them. For this, you need to reverse one border, concatenate the borders and plot them filled. Unfortunately, gnuplot has no function to reverse datapoints in a column, so you have to do it in a special procedure yourself.
The code:
### "Vertical" filledcurves
reset session
# create some dummy data
N = 50
set samples N
set xrange [-5:5]
set table $Data
plot '+' u (sin($1)):1:(rand(0)*0.3+1) with table
unset table
# put Borders into arrays
stats $Data nooutput
RowCount = STATS_records
array BorderX1[RowCount]
array BorderX2[RowCount]
array BorderY[RowCount]
set table $Dummy
plot $Data u (BorderX1[$0+1]=$1-$3):(BorderX2[$0+1]=$1+$3):(BorderY[$0+1]=$2) with table
unset table
# reverse BorderX2 and merge borders
set samples RowCount
set table $Border
plot '+' u (BorderX1[$0+1]):(BorderY[$0+1]) with table
plot '+' u (BorderX2[RowCount-$0]):(BorderY[RowCount-$0]) with table
unset table
# make the plot
set object 1 rect at 0,-3 size 10,0.5 fs solid 1.0 fc rgb "black" back
set yrange[-5:5]
plot \
$Border u 1:2 w filledcurves fc rgb "#AA00FF00" not,\
$Border u ($1*1.5):2 w filledcurves fc rgb "#AAFFFF00" not,\
$Data u ($1+2.5):2 w filledcurves y2 fc rgb "brown" not,\
$Data u 1:2 w l lw 8 lc rgb "blue" not,\
'+' u 1:(cos($1)-0.5):(cos($1)+0.5) w filledcurves lc rgb "grey" not,\
'+' u 1:(cos($1)):(1) w l lw 3 dt 2 lc rgb "white" not
### end of code
The result:
Update: These are two alternative and simpler approaches compared to my first answer. One of them works even with gnuplot 5.0.
The plotting style filledcurves (so far) can only fill between two y-curves with identical x-values. However, gnuplot can fill closed curves. So, make the curve closed. Like in my first answer, you can do this if you reverse one curve and add it to the other one.
The assumption for both scripts is that the data has a common y-column, i.e. is organized in 3 columns, e.g. here: y x1 x2
Data: SO50676753.dat (same as OP's data, from silver.dat in the gnuplot demo directory)
# y x1 x2
10 280 16.7332
20 191 13.8203
30 152 12.3288
40 150 12.2474
50 104 10.1980
60 77 8.7750
70 69 8.3066
80 60 7.7460
90 60 7.7460
100 51 7.1414
110 41 6.4031
120 34 5.8310
130 35 5.9161
140 34 5.8310
150 24 4.8990
160 24 4.8990
170 19 4.3589
180 21 4.5826
190 20 4.4721
200 18 4.2426
210 21 4.5826
220 15 3.8730
230 19 4.3589
240 12 3.4641
250 20 4.4721
260 20 4.4721
270 18 4.2426
280 18 4.2426
290 20 4.4721
300 12 3.4641
310 26 5.0990
320 17 4.1231
330 8 2.8284
340 6 2.4495
350 8 2.8284
360 10 3.1623
370 20 4.4721
380 14 3.7417
390 8 2.8284
400 10 3.1623
410 9 3.0000
420 8 2.8284
430 10 3.1623
440 13 3.6056
450 9 3.0000
460 5 2.2361
470 7 2.6458
480 11 3.3166
500 7 2.6458
510 9 3.0000
520 12 3.4641
530 4 2.0000
540 7 2.6458
550 10 3.1623
560 9 3.0000
580 8 2.8284
590 9 3.0000
600 5 2.2361
Script 1: (works with gnuplot>=5.0.0)
Here you assume that you have monotonic and unique y-values. With this you can use the option smooth unique (available at least in gnuplot 4.x versions) to reverse one curve. However, since this solution here uses datablocks and plotting style with table it requires at least gnuplot 5.0.0. Maybe with some workarounds and temporary files you can also get it to work with some 4.6 versions.
### fill between vertical curves
reset session
FILE = "SO50676753.dat"
set table $Temp
plot FILE u 1:2
plot FILE u (-$1):3 smooth unique
set table $Data
plot $Temp u 2:1 index 0 w table, \
'' u 2:(-$1) index 1 w table
unset table
set style fill solid 0.3
set grid x,y
plot $Data u 1:2 w filledcurves
### end of script
Script 2: (works with gnuplot>=5.2.0)
With this solution there are no special assumptions about the data, but since it uses indexing of datablocks it requires gnuplot>=5.2.0.
### fill between vertical curves
reset session
FILE = "SO50676753.dat"
set table $Temp1
plot FILE u 2:1 w table
set table $Temp2
plot FILE u 3:1 w table
unset table
set print $Data
do for [i=1:|$Temp1|] { print $Temp1[i] }
do for [i=|$Temp2|:1:-1] { print $Temp2[i] } # reverse data
set print
set style fill solid 0.3
set grid x,y
plot $Data u 1:2 w filledcurves
### end of script
Result: (same for both scripts):
Say, I have a large data file that starts at index 1 and ends at more than 10000, like this:
1 -35000 44312 53750 97500 67687 5000 1.64
2 33500 -12937 -68000 -37250 -35937 -96750 1.64
3 -37750 43125 53500 95250 66937 4500 1.64
4 29000 -15437 -69000 -39750 -36562 -97250 1.64
5 -39000 43062 52250 93000 65750 3750 1.64
.
.
.
100000 29250 -14250 -69250 -41500 -37500 -98000 1.64
I use this command to monitor the data online:
plot 'data.raw' using 0:3 title 'Reference' w lp ls 1, \
'data.raw' using 0:7 title 'Temperature' w lp ls 7
set xrange [0: ]
pause 0.5
replot
reread
As the data points increases, I barely see a change in the graph, because I plot the whole file from X=0. How can I plot a certain interval only, e.g. deltaX = 300 points with autoupdate? So I would then see practically 0-300, 300-600, and so on in plot window of Gnuplot.
Thank You!
Not sure if this is what you're after. Say that I have some data file with 1000 entries (generated with bash):
for i in `seq 1 1 1000`; do echo $i $RANDOM >> data; done
Now I plot in intervals of 100 points and visualize each interval during 2 second:
do for [i=1:10] {
set xrange[100*(i-1):100*i]
set title "Interval no. ".i
plot "data" w l
pause 2
}
This looks like so:
I would like to plot below file using gnuplot with a continues line. the problem is that there is a empty line after each point. I can get a graph with points. Could you please help me?
x y type
0 -1866.47 i
100 -1866.52 i
200 -1867.11 i
300 -1868.78 i
400 -1871.58 i
500 -1875.4 i
600 -1880.12 i
700 -1885.62 i
800 -1891.81 i
900 -1898.63 i
1000 -1906.02 i
1100 -1913.94 i
1200 -1922.33 i
1300 -1931.17 i
1400 -1940.43 i
1500 -1950.08 i
1600 -1960.11 i
1700 -1970.49 i
1800 -1981.22 i
1900 -1992.27 i
2000 -2003.63 i
You can filter out the file using an external command. E.g, in a *nix OS, you can use awk:
plot "< awk 'NF!=0 { print $0 }' file.dat" w l
(in awk syntax, NF gives the number of fields in a given line, and $0 contains the entire line)
You can cheat with splot :D
set ticslevel 0
set view 90,0
unset ytics
set xtics offset 0,-1
splot 'empt.txt' u 1:1:2 w l t 'title'
A rather late answer, but already from gnuplot 5.0.0 on (2015), you have the plotting style with table (check help with table). So, you can do it without external tools (platform-independently) and without splot-"cheating".
Simply plot your file (or datablock) in a datablock (or file) which will remove the empty lines.
Script:
### remove empty lines in data
reset session
$Data <<EOD
x y type
0 -1866.47 i
100 -1866.52 i
200 -1867.11 i
300 -1868.78 i
400 -1871.58 i
500 -1875.4 i
600 -1880.12 i
700 -1885.62 i
800 -1891.81 i
900 -1898.63 i
1000 -1906.02 i
1100 -1913.94 i
1200 -1922.33 i
1300 -1931.17 i
1400 -1940.43 i
1500 -1950.08 i
1600 -1960.11 i
1700 -1970.49 i
1800 -1981.22 i
1900 -1992.27 i
2000 -2003.63 i
EOD
set table $NoEmptyLines
plot $Data u 1:2 w table
unset table
plot $NoEmptyLines u 1:2 w l lc rgb "red"
### end of script
Result:
I am using the gnuplot scrip command set key autotitle columnhead to make the lables for my data. The only issue is, the column head data is numeric and so it doesnt really mean much on its own.
Is there a way to add a fixed string to the autotitle, eg "Year " + columnhead, or alternatively, give my key a title?
String concatenation using . operator with columnhead() works in gnuplot v4.6 (documentation):
set terminal pngcairo enhanced truecolor size 480,320 fontscale 0.8
set output 'autotitle.png'
set key left Left
plot for [i=2:4] 'data.txt' u 1:i w l t 'f(x) = '.columnhead(i)
Also, yes, you can set a title for the key instead, like this: set key title 'f(x)'.
Input file data.txt used in this example:
x 100x x^3 2^x
1 100 1 2
2 200 8 4
3 300 27 8
4 400 64 16
5 500 125 32
6 600 216 64
7 700 343 128
8 800 512 256
9 900 729 512
10 1000 1000 1024