gnuplot: 3D plot of a matrix of data - gnuplot

How can I plot (a 3D plot) a matrix in Gnuplot having such data structure,
using the first row and column as a x and y ticks (the first number of the first row is the number of columns) ?
4 0.5 0.6 0.7 0.8
1 -6.20 -6.35 -6.59 -6.02
2 -6.39 -6.52 -6.31 -6.00
3 -6.36 -6.48 -6.15 -5.90
4 -5.79 -5.91 -5.87 -5.46

Exactly this data format can be read in with matrix nonuniform:
set view 50,20
set ticslevel 0
splot 'data.txt' matrix nonuniform with lines t ''
This generates the correct tics, like specified in the data file:

To plot a 4D plot, using colour as the 4th dimension, you can use
splot '1.txt' using 2:3:4:5 every ::1 palette
# | |
# | |
# used for 3d plots skip the header line
Or do you want to draw a different picture, with x and y being the first column and line, and the numbers in the matrix just represinting z? Then use the following:
splot '1.txt' every ::1:1 matrix
To add some effects, you can change it to
set dgrid3d 4,4
splot '1.txt' every ::1:1 matrix with lines

Related

plot data with errorbars and sort them with gnuplot

I have a file statistics.dat with measurements I made. It has the format
node Mean StdDev
1 11862.4 142.871
2 11722.4 141.330
[...]
I can make a sorted graph with plot '< sort -n -k2 statistics.dat' u 2
Now I want to add error bars to my plot. When I use plot 'statistics.dat' u 1:2:3 w errorbars The sorting is obviously lost since gnuplot uses the x- and y-value as coordinates.
Is there a way to plot a sorted graph with errorbars?
Or do I need to sort my data and add new x-values according to the sorded position?
Reading the x coordinate from column 1 is counter-productive in this case. To use the ordering of the sorted file, use column 0 (line number):
plot '< sort -n -k2 statistics.dat' u 0:2:3 w errorbars
Depending on the nature of your data and what you are trying to show in the plot, it may be better to simply use the mean value in column 2 as the x coordinate (no extra sorting required):
plot 'statistics.dat' using 2:2:3 with errorbars
If the original file order has some intrinsic significance you might also want to encode the original order somehow, possibly as x tic labels, possibly as a color range:
plot 'statistics.dat' using 2:2:3:1 with errorbars lc palette

horizontal offset for categorical plot

For the following categorical plot I would like to put some space left of the first category and right of the last:
#abc.dat
a 1
b 2
c 3
In gnuplot:
set yrange [0:4]
plot 'abc.dat' using 2:xticlabels(1) pointtype 7 pointsize 5
Result:
Desired (approximately):
How can this be done? I specifically want points (and not bars).
The command set offsets adds a space between data and axes:
set offsets graph 0.05, graph 0.05
graph ... means a space relative to your plot size.

How to remove line between "jumping" values, in gnuplot?

I would like to draw a line with plots that contain "jumping" values.
Here is an example: when we have plots of sin(x) for several cycles and plot it, unrealistic line will appear that go across from right to left (as shown in following figure).
One idea to avoid this might be using with linespoints (link), but I want to draw it without revising the original data file.
Do we have simple and robust solution for this problem?
Assuming that you are plotting a function, that is, for each x value there exists one and only one corresponding y value, the easiest way to achieve what you want is to use the smooth unique option. This smoothing routine will make the data monotonic in x, then plot it. When several y values exist for the same x value, the average will be used.
Example:
Data file:
0.5 0.5
1.0 1.5
1.5 0.5
0.5 0.5
Plotting without smoothing:
set xrange [0:2]
set yrange [0:2]
plot "data" w l
With smoothing:
plot "data" smooth unique
Edit: points are lost if this solution is used, so I suggest to improve my answer.
Here can be applied "conditional plotting". Suppose we have a file like this:
1 2
2 5
3 3
1 2
2 5
3 3
i.e. there is a backline between 3rd and 4th point.
plot "tmp.dat" u 1:2
Find minimum x value:
stats "tmp.dat" u 1:2
prev=STATS_min_x
Or find first x value:
prev=system("awk 'FNR == 1 {print $1}' tmp.dat")
Plot the line if current x value is greater than previous, or don't plot if it's less:
plot "tmp.dat" u ($0==0? prev:($1>prev? $1:1/0), prev=$1):2 w l
OK, it's not impossible, but the following is a ghastly hack. I really advise you add an empty line in your dataset at the breaks.
$dat << EOD
1 1
2 2
3 3
1 5
2 6
3 7
1 8
2 9
3 10
EOD
plot for [i=0:3] $dat us \
($0==0?j=0:j=j,llx=lx,lx=$1,llx>lx?j=j+1:j=j,i==j?$1:NaN):2 w lp notit
This plots your dataset three times (acually four, there is a small error in there. I guess i have to initialise all variables), counts how often the abscissa values "jump", and only plots datapoints if this counter j is equal to the plot counter i.
Check the help on the serial evaluation operator "a, b" and the ternary operator "a?b:c"
If you have data in a repetitive x-range where the corresponding y-values do not change, then #Miguel's smooth unique solution is certainly the easiest.
In a more general case, what if the x-range is repetitive but y-values are changing, e.g. like a noisy sin(x)?
Then compare two consecutive x-values x0 and x1, if x0>x1 then you have a "jump" and make the linecolor fully transparent, i.e. invisible, e.g. 0xff123456 (scheme 0xaarrggbb, check help colorspec). The same "trick" can be used when you want to interrupt a dataline which has a certain forward "jump" (see https://stackoverflow.com/a/72535613/7295599).
Minimal solution:
plot x1=NaN $Data u 1:2:(x0=x1,x1=$1,x0>x1?0xff123456:0x0000ff) w l lc rgb var
Script:
### plot "folded" data without connecting lines
reset session
# create some test data
set table $Data
plot [0:2*pi] for [i=1:4] '+' u 1:(sin(x)+rand(0)*0.5) w table
unset table
set xrange[0:2*pi]
set key noautotitle
set multiplot layout 1,2
plot $Data u 1:2 w l lc "red" ti "data as is"
plot x1=NaN $Data u 1:2:(x0=x1,x1=$1,x0>x1?0xff123456:0x0000ff) \
w l lc rgb var ti "\n\n\"Jumps\" removed\nwithout changing\ninput data"
unset multiplot
### end of script
Result:

Whether is it possible to plot normal probability distribution in gnuplot

My data file is as-
2 3 4 1 5 2 0 3 4 5 3 2 0 3 4 0 5 4 3 2 3 4 4 0 5 3 2 3 4 5 1 3 4
My requirement is to plot normal PDF in gnuplot.
I could do it by calculating f(x)
f(x) = \frac{1}{\sqrt{2\pi\sigma^2} } e^{ -\frac{(x-\mu)^2}{2\sigma^2} }
for each x using shell script.
Then I plot it in gnuplot using the command-
plot 'ifile.txt' using 1:2 with lines
But whether is it possible to plot directly in gnuplot?
gnuplot provides a number of processing options under the smooth keyword (try typing help smooth for more info). For your specific case, I would recommend a fit though.
First, note that your data points are in a row, you need to convert it to columns for gnuplot to use it. You can do it with awk:
awk '{for (i=1;i<=NF;i++) print $i}' datafile
which can be invoked from within gnuplot:
plot "< awk '{for (i=1;i<=NF;i++) print $i}' datafile" ...
Now assume that datafile has the right format for simplicity.
You can use the smooth frequency option to see how many occurrences of each value you have:
plot "datafile" u 1:(1.) smooth frequency w lp pt 7
To get the normalized distribution, you divide by the number of values. This can be done automatically within gnuplot with stats:
stats "datafile"
This will store the number of values in variable STATS_records, which in you case has value 33:
gnuplot> print STATS_records
33.0
So the normalized distribution (the probability of getting a value at x) is:
plot "datafile" u 1:(1./STATS_records) smooth frequency w lp pt 7
As you can see, your distribution doesn't really look like a normal distribution, but anyway, let's go on. Create a Gaussian for fitting and fit to your data, and plot it. You need to fit to the probability, rather than to the data itself. To do so, we plot to a table to extract the data generated by smooth frequency:
# Non-normalized Gaussian
f(x)= A * exp(-(x-x0)**2/2./sigma**2)
# Save probability data to table
set table "probability"
plot "datafile" u 1:(1./STATS_records) smooth frequency not
unset table
# Fit the Gaussian to the data, exclude points from table with grep
fit f(x) "< grep -v 'u' probability" via x0, sigma, A
# Normalize the gaussian
g(x) = 1./sqrt(2.*pi*sigma**2) * f(x) / A
# Plot
plot "datafile" u 1:(1./STATS_records) smooth frequency w lp pt 7, g(x)
set table generates some points which you should exclude, that's why I used grep to filter the file. Also, the Gaussian needs to be normalized after the fitting is done with a variable amplitude. If you want to retrieve the fitting parameters:
gnuplot> print x0, sigma
3.40584703189268 1.76237558717934
Finally note that if the spacing between data points is not homogeneous, e.g. instead of x = 0, 1, 2, 3 ... you have values at x = 0, 0.1, 0.5, 3, 3.2 ... then you'll need to use a different way to do this, for example defining bins of regular size to group data points.

How do I use gnuplot to plot a simple 2d vector arrow?

This is my first time trying to use gnuplot, and I can't find any instructions on how to accomplish this. The closest I found was this:
http://gnuplot.sourceforge.net/docs_4.2/node259.html
plot 'file.dat' using 1:2:3:4 with vectors head filled lt 2
but I can't find any explanation about "file.dat".
So can somebody give a simple example of how to draw a simple 2d vector arrow? Thanks.
gnuplot has a very good help/documentation build in. Just type help plot or help vector to learn more on how to plot vectors in gnuplot.
The 2D vectors style draws a vector from (x,y) to (x+xdelta,y+ydelta).
A small arrowhead is drawn at the end of each vector.
4 columns: x y xdelta ydelta
This means, your input file should have 4 columns, where the first two columns define the starting (x,y)-position of the vector/arrow and the last two its (x,y) direction:
# file.dat
0 0 .5 .5
0 1 -.5 .5
1 1 1 0
Now typing the following command
plot "file.dat" using 1:2:3:4 with vectors filled head lw 3
gives the following output:
Drawing vectors with the set arrow command
Consider using the set arrow command, if you only need to draw a few vectors/arrows (e.g. to highlight some points in the plot).
set arrow 1 from pi/2,1 to pi/2,0
set arrow 2 from pi*3/2,-1 to pi*3/2,0
plot[0:2*pi] sin(x)
You can create 'file.dat' in a spreadsheet save it as text and put it in the path of gnuplot by using the cd command to point gnuplot to its location. If that does not agree with you, look at the examples using '+' and '++' and '-' in the gnuplot manual. These are a "virtual data file." Note that the first two are for one and two column data points i.e. (x) or (x,y). You will have to use $1 and $2 as variables for calculating dx and dy. It is obligatory to set the xrange and yrange variables and the isosamples for density for this to work.
Something like....
set isosamples 30
set samples 30
set xrange [-10:10]
set yrange [-10:10]
plot '++' using 1:2:(0.1*sin($1)):(0.1*cos($2)) with vectors

Resources