12

I have 2 dat files:

a.dat
#Xs
100   25
200   56
300   75
400   67


b.dat
#Xs
100   65
200   89
300   102
400   167

I want to draw a graph in the gnuplot where the yy values are a ratio between the values of a.dat and b.dat respectively. e.g., 25/65, 56/89, 75/102, and 67/167.

How I do this? I only know make a plot like this, and not with the ratio.

plot "a.dat" using 1:2 with linespoints notitle
     "b.dat" using 1:2 with linespoints notitle
xeon
  • 323
  • 3
  • 15

4 Answers4

17

You cannot combine the data from two different files in a single using statement. You must combine the two files with an external tool.

The easiest way is to use paste:

plot '< paste a.dat b.dat' using 1:($2/$4) with linespoints

For a platform-independent solution you could use e.g. the following python script, which in this case does the same:

"""paste.py: merge lines of two files."""
import sys

if (len(sys.argv) < 3):
    raise RuntimeError('Need two files')

with open(sys.argv[1]) as f1:
    with open(sys.argv[2]) as f2:
        for line in zip(f1, f2):
            print line[0].strip()+' '+line[1],

And then call

plot '< python paste.py a.dat b.dat' using 1:($2/$4) w lp

(see also Gnuplot: plotting the maximum of two files)

Community
  • 1
  • 1
Christoph
  • 47,569
  • 8
  • 87
  • 187
  • I love numpy as much as the next guy, but I think that it's use here is a bit excessive. You could accomplish the same thing with "vanilla" python by `zip`ing 2 file objects. – mgilson Nov 19 '13 at 21:00
  • @mgilson You are right, I added a possible implementation of `paste.py` with 'vanilla' python. Feel free to correct it! It also has the advantage, that it is much more flexible then the `numpy` implementation since it doesn't parse the files before merging them. – Christoph Nov 20 '13 at 08:54
  • 1
    +1 for a portable solution. Since python [2.7](http://docs.python.org/dev/whatsnew/2.7.html#other-language-changes) and [3.1](https://docs.python.org/3.1/reference/compound_stmts.html#with), it is possible to combine `with` statements, so you can do `with open(sys.argv[1]) as f1, open(sys.argv[2]) as f2:` and reduce the level of nesting. – Tom Fenech Jul 18 '14 at 14:44
  • 1
    Following a duplicate of this question, I post another answer. I think it's interesting to point out the `join` command, not that easily portable but allowing to merge files on column values. – Joce Jun 09 '15 at 11:40
5

The short answer is that... you cannot. Gnuplot processes one file at a time.

The work-around is to use an external tool, e.g. using the shell if you have a unix-like, or gnuplot.

join file1 file2 > merged_file will allow you to merge your files quite easily if the first column is identical in both files. Options allow to join on other columns and manage data missing in either file.

In case there is no common column but hte line number is relevant, paste will do.

In case interpolation is required, because the grids in the two files differ, you have to code this. I have a command-line utility that I distribute as free open-source software and can help: datamerge.

Joce
  • 2,220
  • 15
  • 26
0

There is a trick if the two datasets don't fit (different sampling in x), but you have a good mathematical model for at least one of them:

fit f2(x) data2 us 1:2 via ...
set table $corr
plot data1 using 2:(f2($1))
unset table

plot $corr using 1:2

This is of course nonsense if both datasets have the same set of independent variables, because you can simply combine them (see other answers).

Karl
  • 2,117
  • 13
  • 26
0

Just for fun, there is a gnuplot-only and platform-independent solution.

For sure, the command plot '< paste a.dat b.dat' using 1:($2/$4)' from Christoph's answer is unbeatable short (and certainly efficient) in case you are working under Linux or installed the CoreUtils from GnuWin under Windows.

The solution below takes the detour via two long strings. This should work fine unless there is a length limit of strings in gnuplot. I tested only until 100'000 data lines, which will take quite a few minutes. The assumption is that the two files have equal lines with identical x-values. For gnuplot>=5.0 you could write into a datablock instead of a file on disk and do further optimizations.

Script: (works with gnuplot>=4.6.0, March 2012)

### get ratio of numbers from different files
reset 

FILE1 = "SO20069641a.dat"
FILE2 = "SO20069641b.dat"
FILE  = "SO20069641.dat"

# create some random test data
set samples 100
set table FILE1
    plot '+' u (int($0+1)*100):(int(rand(0)*100)+1)
set table FILE2
    plot '+' u (int($0+1)*100):(int(rand(0)*100)+1)
unset table

a = ''
b = ''
stats FILE1 u (a=a.' '.strcol(1).' '.strcol(2)) nooutput
stats FILE2 u (b=b.' '.strcol(1).' '.strcol(2)) nooutput

set table "SO20069641.dat"
    set samples words(a)/2
    splot '+' u (n=2*(int($0+1)),real(word(a,n-1))):(real(word(a,n))):(real(word(b,n)))
unset table

plot FILE u 1:($2/$3) w impulses
### end of script

Result:

enter image description here

theozh
  • 22,244
  • 5
  • 28
  • 72