Gnuplot, how to invert x with y while plotting file data? - graphics

I have a 'data.txt' file containing two columns and N rows, corresponding to N points, e.g.
0.2 0.3
0.4 0.6
0.1 0.7
0.9 0.6
If I use Gnuplot to plot data from this file, using the command
plot "datafile.txt" with lp
it plots every point in the default form (X, Y), that is Gnuplot interprets the first column as all the X values, and the second column as all the Y values.
I would like to invert the meaning of X and Y. I would like to set Gnuplot this command: "Take the first column as Y, and the second column as X"
And so I would like Gnuplot to take all the data from file like (Y,X) and plot them as (X,Y).
How could I do this?
Thanx

gnuplot> plot "./data.txt" using 2:1 with lp
"using" will allow you to select arbitrary columns from your data.

Related

gnuplot arrow coordinates (x,y) error columns

I'm new in gnuplot and my aim is to plot arrows between each data coordinate. My ".dat" file has only two columns, separated by a single tab, where the first is the X and the second is the Y component. The head should be set in the next coordinate.
582.761 -326.288
574.806 -327.915
My command was:
plot 'file.dat' using 1:2 with vectors head filled
I only can obtain the following error message:
Not enough columns for this style
Sorry for the dumb question, but I couldn't understand neither the documentation nor other questions in the same subject.
If you check help vectors you will see that with vectors plotting style requires 4 values.
And if I understand your question correctly I guess you want to plot arrows from one data line to the next data line, correct?
By the expression (x0=x1,x1=$1,x0) you keep the previous x value in x0 and the current value in x1, but you're plotting x0. Same for y0 and y1. And (x1-x0) and (y1-y0) are simply the delta x and delta y values which you need for the with vectors plotting style.
Code:
### vectors from data line to the next
reset session
$Data <<EOD
1 1
2 2
3 5
2 4
1 2
EOD
x1=y1=NaN
plot $Data u (x0=x1,x1=$1,x0):(y0=y1,y1=$2,y0):(x1-x0):(y1-y0) w vectors head filled notitle
### end of code
Result:

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.

Plotting a series using gnuplot (Maclaurin series)

Is there a quick way to plot the Maclaurin/Taylor series using Gnuplot. For eg:
http://en.wikipedia.org/wiki/Power_series
I'm trying to plot each term of the series NOT the series f(x) vs x.
So, for sin(x) I'd like to plot on the x-axis, x, -x^3/3!, x^5/5! etc and the sum itself all on one axis without having to type each term in the sequence manually.
You can plot functions in gnuplot. In this case, you would have to define your series, for example:
gnuplot> a0 = 1
gnuplot> a1 = 0.5
gnuplot> a2 = 0.1
gnuplot> f(x) = a0 + a1*x**2 + a2*x**3
gnuplot> plot f(x)
This will give you:
Edit
Based on the comment to this answer, I'm proposing this (which should work for gnuplot 4.4 and higher):
First, define your factorial:
gnuplot> fac(n) = (n==0) ? 1 : n * fac(n-1)
Second, iterate over as many terms as you like (in this case 10). We're only interested in the uneven exponents, hence the upper bound is 20. Furthermore, every other "term" has to be multiplied by -1, thus two commands, and an increment of 4:
plot for [a=3:21:4] -1*x**a/fac(a), for [a=1:21:4] x**a/fac(a)
This will give you a plot like this:

gnuplot: 3D plot of a matrix of data

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

Resources