30

I'm trying to produce a plot with two lines using data taken from stdin. I have a file "test.csv":

0,1.1,2
1,2,3
2,6,4
4,4.6,5
5,5,6

I've been trying to plot this with commands like,

$ cat test | gnuplot -p -e "set datafile separator \",\"; plot '-' using 1:2 with lines, '' using 1:3 with lines;"

But no matter what I try I get,

line 5: warning: Skipping data file with no valid points

I assume this is because for the second line, stdin has already been exhausted. Is there a way to get gnuplot to take data from each column of stdin for different plots?

Thanks.

Steve
  • 8,153
  • 9
  • 44
  • 91
  • Could a `set` command be used instead of the `using` clause? Maybe that could allow a use of `replot`?...Hmm, probably not ideal; we want one `plot` command here, right? – user2023370 Jan 03 '12 at 11:52

9 Answers9

19

The "-" is used to specify that the data follows the plot command. So if you use it, you'll need to do something like:

echo "set datafile separator \",\"; plot '-' using 1:2 with lines, '' using 1:3 with lines;" | cat - datafile.dat | gnuplot -p

(Quoting above probably needs to be escaped).

What're you looking for is this:

plot '< cat -'

Now, you can do:

cat test | sed ... | gnuplot -p "plot '< cat -' using ..."

Note that you might need to feed in the input data via stdin multiple times if you're using options with plot, like so:

cat testfile testfile | gnuplot -p "plot '< cat -' using 1, '' using 2"

In the above case, testfile must end with a line that has the sole character 'e' in it.

Manual reference

PonyEars
  • 2,144
  • 4
  • 25
  • 30
12

I managed to work around this by sending the data twice, terminated by am "e" on it's own line after each block. So your input should look like

set datafile separator ","; plot '-' using 1:2 with lines, '' using 1:3 with lines
0,1.1,2
1,2,3
2,6,4
4,4.6,5
5,5,6
e
0,1.1,2
1,2,3
2,6,4
4,4.6,5
5,5,6
e
bdew
  • 1,330
  • 9
  • 22
10

Gnuplot can read from stdin, but for each plot statement, a new data set is required. The following works fine:

cat test.csv | gnuplot -p -e "set datafile separator ','; plot '-' using 1:2 w l"

The error appears as soon as you append the second plot command with , '' using 1:3. For this you need to send the data again as the first data set isn't stored interally for reuse. So for you two plot commands, the following snippet works fine:

echo 'e' | cat test.csv - test.csv | gnuplot -p -e "set datafile separator ','; plot '-' using 1:2 w l, '' using 1:3 w l"

That writes the data file twice, separated by an e which indicates the end of the data for the first plot command.

Christoph
  • 47,569
  • 8
  • 87
  • 187
2

Have you tried chart? Your case would be as easy as:

cat test | chart line ','

And would give you:

line chart

mlg
  • 1,447
  • 15
  • 19
  • Doesn't answer the question, but extremely useful to me. Thanks! I get tired of having to look up gnuplot junk every time I want to plot some simple data. – Benny Jobigan Apr 07 '23 at 07:52
2

I'd try converting the csv file to space separated (assuming no of the records span multiple lines) by piping it through sed instead of setting the separator:

cat test | sed 's/,/ /g' | gnuplot -p -e "plot '-' using ..."
arnsholt
  • 851
  • 7
  • 17
  • Oh, I think I just saw it. You're missing the dash in the second part of the plot command. Make it `plot '-' using 1:2 with lines, '-' using 1:3 with lines;` and I think it should work. – arnsholt Jan 04 '11 at 14:16
  • 1
    Nope, sorry. The missing dash just means "Use the same file as previously". – Steve Jan 07 '11 at 18:37
1

Maybe this is an old question but I've found an interesting solution based on the other answers:

cat filename | awk -- '{print $0} END{print "e"}' | tee -i -a - -

The output would be:

"contents of filename"
e
"contents of filename"
e
"contents of filename"
e

Now cat and awk work as usual, the utility tee on the other hand allows us to copy the standard output piped from the previous command to a file, but this file can be stdin itself so we can make many copies of it, by specifying n times - after -a.

The option -i stops it being interrupted by signals during the copy, -a tells it to append the input to standard input without overwriting and then write the whole thing to stdout.

For reference take a look at Tee Utility

agc
  • 7,973
  • 2
  • 29
  • 50
robotik
  • 9
  • 3
  • Using the `tee` utility seems nice, but your command line as you posted it doesn't work at all for me. I tried both with `gawk` and `mawk`, but I get only three `e` as output (I used a real file in the `cat`). – Christoph Aug 12 '14 at 19:21
  • you're right i forgot to add {print $0} in the awk script, i'll edit the answer to fix it – robotik Aug 12 '14 at 20:16
  • `tee` writes to all its arguments, including stdout, if there are enough lines the data will get intermixed. You can see this by sending many lines to tee eg. with seq: `seq 10000 | tee -i -a -`. – Thor May 06 '15 at 06:35
0

gnuplot seems to need random access (i.e. not stdin), so I think you're stuck with

# explicitly open "test" file
$ gnuplot -p -e "set datafile separator \",\"; plot 'test' using 1:2 with lines, '' using 1:3 with lines;"
Rhythmic Fistman
  • 34,352
  • 5
  • 87
  • 159
0

I had to do the following, since adding '-' did not work for me:

 cat filename | awk -- '{print $0} END{print "e"}' | tee -i -a /dev/stdout /dev/stdout 
LEo
  • 477
  • 5
  • 14
0

For me this works when I do:

set datafile separator ','
plot "test.csv" using 1:2 with lines

it seems that you used "," for datafile separator instead of ','

Martin
  • 1,084
  • 9
  • 15
  • 1
    The quotes don't make a difference. The problem is with `stdin`, not with the separator. In your example, you specified `test.csv`, which indeed works fine but does not answer the question. – Steve Mar 01 '11 at 18:36