Fitting one dataset as a function of other datasets in gnuplot - gnuplot

I assume one dataset ist the mixture of two other datasets, but don't know exactly how to calculate this in gnuplot. Practically, I want to "fit" dataset3 by dataset2 and dataset1 using a function like this:
output = a*(dataset1) + b*(dataset2)
to get a and b.

Assuming you have some data like this:
1 1 6.95322
1 2 10.9421
1 3 14.9826
1 4 19.4772
2 1 10.03
2 2 13.8502
2 3 17.9662
2 4 21.9018
3 1 12.7868
3 2 16.8742
3 3 21.0967
3 4 24.3392
4 1 16.4094
4 2 20.2189
4 3 24.5766
4 4 27.1483
You can write your function "output=a*(dataset1)+b*(dataset2)" and fit it like this:
f(x,y) = a*x + b*y
fit f(x,y) "a.dat" using 1:2:3 via a,b
The result:
...
Final set of parameters Asymptotic Standard Error
======================= ==========================
a = 3.02235 +/- 0.06193 (2.049%)
b = 3.95873 +/- 0.06193 (1.564%)
...
I have generated the example data with a=3 and b=4.

This is basically identical with maij's solution, but with copy&paste&run code, including "x"-data, and illustration. Everytime, it creates some spectra with random noise. Just skip this part and replace $Data with your file. In case you have your datasets in different files you either have to copy them togther or play some tricks with gnuplot. Make sure that the "x"-coordinate and step size is identical for all datasets, otherwise you would have to interpolate to have identical x-values.
Code:
### fit to find superposition factors
reset session
# generate some random test data
f1(x) = exp(-(x**2)/5) + rand(0)*0.05
f2(x) = exp(-((x-4)**2)/5) + rand(0)*0.05
a0 = int(rand(0)*10+5)
b0 = int(rand(0)*10+2)
f3(x) = a0*f1(x) + b0*f2(x) + rand(0)*0.05
set table $Data
plot '+' u 1:(f1(x)):(f2(x)):(f3(x)) w table
unset table
set fit quiet results
f(x,y) = a*x + b*y
fit f(x,y) $Data using 2:3:4 via a,b
plot \
$Data u 1:2 w lp pt 7 ps 0.4 ti "Dataset 1", \
'' u 1:3 w lp pt 7 ps 0.4 ti "Dataset 2", \
'' u 1:4 w lp pt 7 ps 0.4 ti "Dataset 3", \
'' u 1:(a*$2 + b*$3) w l lw 2 \
ti sprintf("\n\n\nSuperposition\n D3 = a*D1 + b*D2\na: %g\nb: %g", a,b)
### end of code
Result:

Related

How to plot points specified by ID column only with linespoints and multiple plots using gnuplot?

Say I have two files, each has 3 columns
file1:
ID X Y
10 0.1 some data as X
20 0.2
30 0.3
... ...
120 0.5
file2:
ID X Y
15 0.1 some data as X
30 0.2
45 0.3
60 0.4
... ...
120 0.6
I am doing
plot \
"file1" using 2:3 w linespoints lt 1 dt 1 lw 1 lc 1 title "file1",\
"file2" using 2:3 w linespoints lt 1 dt 1 lw 1 lc 2 title "file2"
which shows every point on the file.
If I only want points which its Row ID(first column) is 30, 60 ,90 ,120
How should I do? Thank you.
*In the actually case, I need to plot 12 file in one plot and each of them have 10000 rows but I only want to show 6 points.
You can filter your data with the ternary operator. Check help ternary.
For the filename and the filter I would define a function such that you have it compact in your plot command.
What myFilter(dcol,fcol) does is returning the value of the data column dcol if the filter column fcol is equal to one of the given values.
myFilename(n) creates the filename as a function of a number.
I don't have test files but the following should plot the 12 files names "file1.dat", ..., "file12.dat".
I hope you can adapt it to your exact needs.
Code:
### filter data with ternary operator
reset session
myFilename(n) = sprintf("file%d.dat",n)
myFilter(dcol,fcol) = column(fcol)==30 || column(fcol)==60 || \
column(fcol)==90 || column(fcol)==120 ? column(dcol) : NaN
set datafile missing NaN
plot for [i=1:12] myFileName(i) u 2:(myFilter(3,1)) w lp ti myFilename(i)
### end of code

categorising points by using of gnuplot

I am going to plot a file containing 4 columns. first and second column are x and y respectively. I want to categorize these point based on the third and fourth column. In fact, the third column should display the color (red or blue) of point and the fourth column should determine its type (square or circle ). how could I reach to this goal by gnu-plot?
I should mention that I tried this, by it does not work!
set style line 1 lc rgb 'red' pt 7
set style line 2 lc rgb 'red' pt 7
set style line 3 lc rgb 'blue' pt 9
set style line 4 lc rgb 'blue' pt 9
plot 'data' w ($3= 1 && $4= 1) ? p ls 1 \
: ($3= 1 && $4= 2) ? p ls 2 \
: ($3= 2 && $4= 1) ? p ls 3 \
: ($3= 2 && $4= 2) ? p ls 4
Please check help points. From the manual:
plot DATA using x:y:pointsize:pointtype:color \
with points lc variable pt variable ps variable
You don't show sample data. If you can adjust your data, the easiest would be the following below.
If you want to set the color by name in your file, check this.
Code:
### variable pointtype and color
reset session
$Data <<EOD
1 2 5 0xff0000
3 4 7 0xff0000
5 6 5 0x0000ff
7 8 7 0x0000ff
EOD
plot $Data u 1:2:3:4 w p ps 5 pt var lc rgb var
### end of code
Result:

How to display multiple symbols per line in gnuplot legend?

In gnuplot I have multiple datasets and wish to display on one line of the legend two different symbols. Here's what I currently have:
What I would like is to have to the square and the triangle to be on the same line. I am using the epslatex terminal. Thanks a lot.
You will have to do it by hand.
The most reliable way is probably to make all the key by hand :
Remove all automatic key by issuing unset key
Set custom variables to position your key:
KEY_X=0.1
KEY_Y=0.9
JUMP=0.05
IDX=1
For each plot command, issue before it a corresponding set label (point styles) or set arrow (line styles). E.g.,
set label IDX "a" at graph KEY_X,graph KEY_Y+(IDX-1)*JUMP left point pt 7 lc IDX offset 2
replot x with points pt 7 lc IDX
IDX=IDX+1
Thus you can add an empty label at the desired position when it comes to have two series with the same key.
Just in case this might still be of interest. Here are two ugly workarounds:
reduce the key spacing to 0.5 and plot two NaN dummies with ps 0 and set title "\n".
The symbols will not be (horizontally) next to each other but at least (vertically) close to each other.
set maxrow 3 and samplen 0 and plot one NaN dummy. Although the symbols are (horizontally) next to each other, currently, I don't have an idea how to get them closer to each other.
Code:
### "one" key entry with two symbols
reset session
set samples 20
set multiplot layout 1,2
set key top center spacing 0.5
plot x w p pt 7 ps 1 lc "red" title "a", \
NaN w p ps 0 title "\n", \
x*2 w p pt 5 ps 1 lc "blue" title "b", \
x*3 w p pt 9 ps 1 lc "black" title "\n", \
NaN w p ps 0 title "\n", \
x*4 w l dt 2 lw 1 lc "black" title "c"
set key top center maxrow 3 spacing 1 samplen 0
plot x w p pt 7 ps 1 lc "red" title "a", \
x*2 w p pt 5 ps 1 lc "blue" title "b", \
x*4 w l dt 2 lw 1 lc "black" title "c", \
NaN w p ps 0 title "\n", \
x*3 w p pt 9 ps 1 lc "black" title "\n"
unset multiplot
### end of code
Result:

Gnuplot: plotting points with variable point types

I have x,y values for points in the first 2 colums and a number that indicates the point type (symbol) in the 3. column, in one data file. How do I plot data points with different symbols?
Unfortunately, there isn't a way (AFAIK) to automatically set the point of the plot from a column value using vanilla GNUPLOT.
However, there is a way to get around that by setting a linestyle for each data series, and then plotting the values based on that defined style:
set style line 1 lc rgb 'red' pt 7 #Circle
set style line 2 lc rgb 'blue' pt 5 #Square
Remember that the number after pt is the point-type.
Then, all you have to do is plot (assuming that the data in "data.txt" is ordered ColX ColY Col3):
plot "data.txt" using 1:2 title 'Y Axis' with points ls 1, \
"data.txt" using 1:3 title 'Y Axis' with points ls 2
Try it here using this data (in the section titled "Data" - also note that column 3 "Symbol" is noted used, it's mainly there for illustrative purposes):
# This file is called force.dat
# Force-Deflection data for a beam and a bar
# Deflection Col-Force Symbol
0.000 0 5
0.001 104 5
0.002 202 7
0.003 298 7
And in the Plot Script Heading:
set key inside bottom right
set xlabel 'Deflection (m)'
set ylabel 'Force (kN)'
set title 'Some Data'
set style line 1 lc rgb 'red' pt 7
set style line 2 lc rgb 'blue' pt 5
plot "data.txt" using 1:2 title 'Col-Force' with points ls 1, \
"data.txt" using 1:3 title 'Beam-Force' with points ls 2
The one caveat is of course that you have have to reconfigure your data input source.
REFERENCES:
http://www.gnuplotting.org/plotting-single-points/
http://www.gnuplotting.org/plotting-data/
Here is a possible solution (which is a simple extrapolation from gnuplot conditional plotting with if), that works as long as you don't have tens of different symbols to handle.
Suppose I want to plot 2D points in a coordinate system. I have only two symbols, that I arbitrarily represented with a 0 and a 1 in the last column of my data file :
0 -0.29450470209121704 1.2279523611068726 1
1 -0.4006965458393097 1.0025811195373535 0
2 -0.7109975814819336 0.9022682905197144 1
3 -0.8540692329406738 1.0190201997756958 1
4 -0.5559651851654053 0.7677079439163208 0
5 -1.1831613779067993 1.5692367553710938 0
6 -0.24254602193832397 0.8055955171585083 0
7 -0.3412654995918274 0.6301406025886536 0
8 -0.25005266070365906 0.7788659334182739 1
9 -0.16853423416614532 0.09659398347139359 1
10 0.169997438788414 0.3473801910877228 0
11 -0.5252010226249695 -0.1398928463459015 0
12 -0.17566296458244324 0.09505800902843475 1
To achieve what I want, I just plot my file using conditionals. Using an undefined value like 1/0 results in no plotting of the given point:
# Set styles
REG_PTS = 'pointtype 7 pointsize 1.5 linecolor rgb "purple"'
NET_PTS = 'pointtype 4 pointsize 1.5 linecolor rgb "blue"'
set grid
# Plot each category with its own style
plot "data_file" u 2:($4 == 0 ? $3 : 1/0) title "regular" #REG_PTS, \
"data_file" u 2:($4 == 1 ? $3 : 1/0) title "network" #NET_PTS
Here is the result :
Hope this helps
Variable pointype (pt variable) was introduced (I guess) not until gnuplot 5.2.0 (Sept 2017) (check help points).
Just in retrospective, another (awkward) solution would be the following for those who are still using such early versions.
Data:
1 1.0 4 # empty square
2 2.0 5 # filled square
3 3.0 6 # empty circle
4 4.0 7 # filled circle
5 5.0 8 # empty triangle up
6 6.0 9 # filled triangle down
7 7.0 15 # filled pentagon (cross in gnuplot 4.6 to 5.0)
Script: (works from gnuplot>=4.6.0, March 2012; but not necessary since 5.2.0)
### variable pointtype for gnuplot>=4.6
reset
FILE = 'SO23707979.dat'
set key noautotitle
set offsets 1,1,1,1
set pointsize 4
stats FILE u 0 nooutput
N = STATS_records # get the number of rows
p0=x1=y1=NaN
plot for [n=0:N-1 ] FILE u (x0=x1, x1=$1, x0):(y0=y1, y1=$2, y0):(p0=$3) \
every ::n::n w p pt p0 lc rgb "red", \
FILE u 1:2 every ::N-1::N-1 w p pt p0 lc rgb "red"
### end of script
Result:

Plot cyclic sum of some row data

I have a data file that store for a given timestamp k values.
Ex:
# data.dat
# Example for k = 3
# Time ID value
1 0 1.555
1 1 1.76
1 2 12.56
2 0 1.75
2 1 2.04
2 2 13.04
3 0 2.01
3 1 0.52
3 2 12.99
# ...
I can print individually the data of each ID versus the time as follows:
set xrange [0:4]
set yrange[0:14]
set xtics 1
plot "data.dat" every 3 using 1:3 title "ID=0" with lp, \
"" every 3::1 using 1:3 title "ID=1" with lp, \
"" every 3::2 using 1:3 title "ID=2" with lp
Yet I'm interested to plot the average sum of the 3 values vs time.
Of course, I could regenerate a new data file containing (with evaluated sum):
# avg_data.dat modified to
# Example for k = 3
# Time ID value
1 (1.555+1.76+12.56)/3
2 (1.75+2.04+13.04)/3
3 (2.01+0.52+12.99)/3
# ...
But of course, I'm seeking an automated way do express that in gnuplot using the data.dat file directly...
Drawing some inspiration from the running average demo on the gnuplot site:
k = 3
back1 = back2 = back3 = 0
shifter(x) = (back3 = back2, back2 = back1, back1 = x)
avger(x,y) = (shifter(x), y == k - 1 ? (back1 + back2 + back3)/3 : 1/0)
plot 'data.dat' u 1:(avger($3, $2)) with points pt 7
This works for me in gnuplot 4.6.1. If you want to have the points at each timestep connected in a line, it may be better to preprocess the data, since gnuplot in general won't connect points resulting from an expression evaluation (see discussion here and here, and in the gnuplot docs for set datafile missing).

Resources