31

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.

1
  • 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? Commented Jan 3, 2012 at 11:52

9 Answers 9

21

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

Sign up to request clarification or add additional context in comments.

Comments

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

1 Comment

Is there a way to put the data from each plot on one line. e.g. : 0,1.1,2 1,2,3 2,6,4 4,4.6,5 5,5,6 e
12

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.

Comments

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 ..."

2 Comments

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.
Nope, sorry. The missing dash just means "Use the same file as previously".
2

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

cat test | chart line ','

And would give you:

line chart

1 Comment

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.
1

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 

Comments

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

3 Comments

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).
you're right i forgot to add {print $0} in the awk script, i'll edit the answer to fix it
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 -.
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 ','

1 Comment

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.
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;"

2 Comments

Right you are, it can read from stdin, but you still need a temporary file, so why not pass it in?
Right, it doesn't make much sense, if you have a file anyway. But it explains the error :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.