gnuplot plotting multiple line graphs - gnuplot

I have the following dat file, named ls.dat:
# Gnuplot script file for "ls"
# Version Removed Added Modified
8.1 0 0 0
8.4 0 0 4
8.5 2 5 9
8.6 2 7 51
8.7 2 7 51
8.8 2 7 51
8.9 2 7 51
8.10 2 7 51
8.11 2 8 112
8.12 2 8 112
8.13 2 17 175
8.17 6 33 213
I am trying to plot with this:
plot "ls.dat" using 1:2 title 'Removed' with lines,\
"ls.dat" using 1:3 title 'Added' with lines,\
"ls.dat" using 1:4 title 'Modified' with lines
This produces the following graph:
What I am expecting is three line plots which should all go up, but at different rates. Can anyone see what is going on here? I'm sure it must be something very silly.

I think your problem is your version numbers. Try making 8.1 --> 8.01, and so forth. That should put the points in the right order.
Alternatively, you could plot using X, where X is the column number you want, instead of using 1:X. That will plot those values on the y axis and integers on the x axis. Try:
plot "ls.dat" using 2 title 'Removed' with lines, \
"ls.dat" using 3 title 'Added' with lines, \
"ls.dat" using 4 title 'Modified' with lines

andyras is completely correct. One minor addition, try this (for example)
plot 'ls.dat' using 4:xtic(1)
This will keep your datafile in the correct order, but also preserve your version tic labels on the x-axis.

In addition to the answers above the command below will also work. I post it because it makes more sense to me. In each case it is 'using x-value-column: y-value-column'
plot 'ls.dat' using 1:2, 'ls.dat' using 1:3, 'ls.dat' using 1:4
note that the command above assumes that you have a file named ls.dat with tab separated columns of data where column 1 is x, column 2 is y1, column 3 is y2 and column 4 is y3.
Edit for .csv file types....
Note if you have a .csv file then if you use the gnuplot command
set datafile separator comma
you can then use the plot command above for data files where the numbers are separated by commas.

Whatever your separator is in your ls.dat, you can specify it to gnuplot:
set datafile separator "\t"

Related

Understanding the use of the keyword every

My question regards the keyword every that is used to sample an input data file (i.e., .csv, .dat etc.). I am reading the documentation of the keyword that says the following:
plot 'file' every {<point_incr>}
{:{<block_incr>}
{:{<start_point>}
{:{<start_block>}
{:{<end_point>}
{:<end_block>}}}}}
The thing is I cannot completely comprehend how to adapt this to a data set. For instance, if I have some dummy data that I wish to use to create a bar chart for example and the data are the following
# first bars group
#x axis #y axis
0 2
0.2 3
0.4 4
0.6 5
0.8 6
#second bars group
1 1
1.2 2
1.4 3
1.6 4
1.8 5
#etc.
3 10
3.2 20
3.4 30
3.6 40
3.8 50
4 20
4.2 30
4.4 40
4.6 50
4.8 60
And lets say that I want to create four bar clusters from the data. One for every block. How can I use the syntax of the keyword? Could someone give me some examples to better understand the use of it? Thank you in advance
As you've found, the every keyword allows you to cherry-pick a subset of single-newline-separated points and double-newline-separated blocks from your datafile. Your example datafile shows 20 points divided into 4 blocks.
So to plot the first block (indexed 0 in gnuplot), you only need to specify the end block, and use the default values for the other every parameters. Try:
plot 'data.txt' every :::::0 with boxes
It seems your goal is to plot each block with separate styling. Here's how you could do that with a few extra styling commands. (Note my use of gnuplot's shorthand for some keywords.)
set key left top
set boxwidth 0.2
p 'data.txt' ev :::0::0 w boxes t 'first',\
'data.txt' ev :::1::1 w boxes t 'second',\
'data.txt' ev :::2::2 w boxes t 'third',\
'data.txt' ev :::3::3 w boxes t 'fourth'
From help every:
The data points to be plotted are selected according to a loop from
<start_point> to <end_point> with increment <point_incr> and the
blocks according to a loop from <start_block> to <end_block> with
increment <block_incr>.
This should be pretty clear, however, you have to know if blocks are separated by two (or more) empty lines, you have to address them differently. Check help index. To my opinion the documentation is a bit confusing about datablock, (sub-)block, dataset, etc...
Check the following example. I assume this is not your final graph, but still needs some tuning. Depending on your detailed requirements you also might want to check help histograms.
For example every :::i::i will plot all datapoints in in block i, i.e. from block i to block i.
Code:
### plotting using "every"
reset session
$Data <<EOD
# first bars group
#x axis #y axis
0 2
0.2 3
0.4 4
0.6 5
0.8 6
#second bars group
1 1
1.2 2
1.4 3
1.6 4
1.8 5
#etc.
3 10
3.2 20
3.4 30
3.6 40
3.8 50
4 20
4.2 30
4.4 40
4.6 50
4.8 60
EOD
set key top left
set boxwidth 0.2
set key out noautotitles
set style fill solid 0.3
set yrange [:70]
plot for [i=0:3] $Data u 1:2 every :::i::i w boxes
### end of code
Result:

How to sprintf() last data value in Gnuplot key?

I'm working on a temperature graph and would like to put the last data point in the title. I can use column(2) to kind of do this but I'd like to add some descriptive text as well. I'm trying the code below to concatentate some text with the data value but getting this error: line 0: f_sprintf: attempt to print numeric value with string format
plot "/tmp/data.txt" using 1:2 with lines ls 2 title sprintf('Current :%sF', column(2))
I've tried changing the sprintf modifer to %d along with various flavors of concatenation with the dot character and haven't found the right combination.
Most probably there are various solutions. The first possibility which comes to my mind (I guess requiring gnuplot >5.2) is using keyentry, check help keyentry. While plotting you are asigning column 2 to a variable. After plotting, this variable holds the last value of column 2, which you use later in keyentry, which is a keyentry without plotting anything. There would also be workarounds for older gnuplot versions.
Code:
### last value into key
reset session
$Data <<EOD
1 7.1
2 6.2
3 5.3
4 4.4
5 3.5
6 2.6
7 1.7
8 0.8
EOD
plot $Data u 1:(a=$2) w lp pt 7 lc 1 notitle, \
keyentry w lp pt 7 lc 1 ti sprintf("Last y value: %g",a)
### end of code
Result:
The problem here is that the title string is evaluated by gnuplot before the data is parsed and plot is performed.
A trick is to store the last value of temperature, and plot it afterwards.
T=0
plot "/tmp/data.txt" using 1:(T=column(2)) w l ls 2 notitle, \
1/0 w l ls 2 title sprintf('Current: %.1fF', T)

Jitter points in gnuplot. Data input file format

I am able to successfully reproduce Jitter examples from here: http://gnuplot.sourceforge.net/demo/violinplot.html
However, when I try to use my own data, the points are not "jittered".
Here is the data file (data.dat):
10 1 1 3 8 8 8
20 2 2 3 8 8 8
30 3 3 3 8 8 8
Here is a minimal gnuplot input file:
set jitter
plot 'data.dat' using 1:2 with points, '' u 1:3 with points, '' u 1:4 with points, '' u 1:5 with points, '' u 1:6 with points, '' u 1:7 with points
The points are right on top of each other, whereas I want points that are in the same place to be slightly offset (x-axis).
I've installed the latest version of gnuplot:
$ gnuplot --version
gnuplot 5.2 patchlevel 6
EDIT WITH SOLUTION:
#Ethan's comment cleared it up for me. I'm able to get the jittering by reorganizing my input data file so that it's a single dataset, which contains internal "collisions", rather than reading in lots of individual data sets. e.g:
10 1
10 1
10 3
10 3
20 2
20 2
30 8
30 8
And my gnuplot file is now just:
set jitter
plot 'data.dat' using 1:2 with points
"set jitter" will not work across multiple data sets as noted in the comment. You could do something similar by adding a random displacement in the 'using' specifier.
plot for [col=2:7] 'data.dat' using 1:(column(col) + (rand(0)-0.5)/2.) with points
This is different from "set jitter" because all points will be randomly displaced, whereas with jitter only overlapping points are shifted and the displacement is not random.
Alternatively, since in your case the columns are distinct perhaps you want to shift systematically based on the column number:
plot for [col=2:7] 'data.dat' using (column(1)+col/4.) : (column(col))

Plotting arrows with start and end from two different files

I have two different .txt files with x and y coordinates of equal number of samples in both.
File 1
x y
1 2
5 4
4 6
File 2
x y
5 6
3 4
2 3
I want to connect each of these points inFile 1 with the corresponding points in File 2. I know to draw an arrow between two points it is
set arrow from (x,y) to (c,d)
But how do I get the coordinates of these points from two different files to draw connecting lines/ arrows?
Something like this:
plot "< paste file1.data file2.data" with vectors
Edit: I came across this old answer and was amazed (actually shocked) how inefficient and complicated solutions I suggested.
A much better approach: Since gnuplot 5.2.0 you can index datablocks. Prerequisite is that your data is in a datablock already. See here: gnuplot: load datafile 1:1 into datablock.
If you can be sure that your data files have identical number of lines, you can "mimic" the Linux paste command using a gnuplot-only, hence, platform-independent solution.
Basically, you join the two lines having the corresponding index after removing the last character (newline) of each line.
Script: (works with gnuplot>=5.2.0, Sept. 2017)
### plot arrows across two files, i.e. merge lines with gnuplot only
reset session
$Data1 <<EOD
File 1
x y
1 2
5 4
4 6
EOD
$Data2 <<EOD
File 2
x y
5 6
3 4
2 3
EOD
set print $Combined
do for [i=1:|$Data1|] {
print $Data1[i][1:strlen($Data1[i])-1].' '.$Data2[i][1:strlen($Data2[i])-1]
}
set print
plot $Combined u 1:2:($3-$1):($4-$2) w vec lc rgb "red"
### end of script
Result:

Gnuplot xrange not really a range?

I try to make a plot on gnuplot which has no real range order on x-axis.
--------------------->
1 4 2 20 17 12 10 8
It's therefore not a real function as you would interpret it with math knowledge, but it has some sort of index on its x-axis which has no numbering order and runs from 1-20 but 20 could be the first, or in the middle.. everything may be mixed..
hope you understand what I mean cause I am hoping gnuplot can handle that.
maybe i can write my data file so that point 2 contains the data that should be there on the y-axis and just move the labels around on x-axis?
You could e.g. write a datafile "data" containing such values
1 1.5
4 2
2 3.2
20 2.2
17 0.4
12 4.3
The second column are the "y-values", the first column the labels of the x-axis (xtics)
now try to plot this data with:
plot './data' u 2:xticlabel(1)
is that what you want?
Solution is using xticlabels and add an extra column in the data file.
ie
#xdata ydata label
0 2 1
1 3 14
2 10 0
3 8 20
etc.
command: plot "data.dat" using 1:2:xticlabels(3) with lp"

Resources