1

I have some data in the following format:

10.0 1 a 2
10.2 2 b 2
10.4 3 a 2
10.6 4 b 2
10.8 4 c 10
11.0 4 c 20

... where the third column basically indicates belonging to a 'separate' dataset; and so I would like to show, say, those samples belonging to 'a' in red, those belonging to 'b' in blue etc (using gnuplot Version 4.4 patchlevel 2).

I managed to somehow get the 'sample' style as a mix between 'impulses' and 'point' styles; and via Choosing line type and color in Gnuplot 4.0, managed to employ individual colors - this is how far I got (basictest.gnuplot):

#!/usr/bin/env gnuplot

print "Generating data..."

# to specify data inline in script:
# only system can work, as it is quoted;
# but still have to escape newlines!

system "cat > ./inline.dat <<EOF\n\
10.0 1 a 2\n\
10.2 2 b 2\n\
10.4 3 a 2\n\
10.6 4 b 2\n\
10.8 4 c 10\n\
11.0 4 c 20\n\
EOF\n"

print "done generating."


# set ranges
set yrange [0:30]
set xrange [0:4]

# define line styles - can call them up later
set style line 1 linetype 1 linewidth 3 pointtype 3 linecolor rgb "red"
set style line 2 linetype 1 linewidth 2 pointtype 3 linecolor rgb "green"
set style line 3 linetype 1 linewidth 2 pointtype 3 linecolor rgb "blue"


# offset the X axis: instead of 1:2, use: ($1-10):2
# to "mix", use "" for last datset - but must also repeat the "using"!
# ... and plot:

plot 'inline.dat' using ($1-10):2 with impulses linestyle 1,\
     "" using ($1-10):2 notitle with points linestyle 1,\
     "" using ($1-10):2 notitle with lines linestyle 2,\
     'inline.dat' using ($1-10):4 with impulses linestyle 3,\
     "" using ($1-10):4 notitle with points linestyle 3

# below just for saving file
#set terminal png
#set output 'basictest.png'
#replot

... which looks like this:

basictest.png

In other words, instead of the above - say for ($1-10):2, I'd like to see the 1st and 3rd sample ('a') in blue, 2nd and 4th sample ('b') in red, and the last two ('c') in green (I left the green line there just to see the effect of the style mixing).

I'm aware that this could be achieved by writing a script, that will parse the original data, and generate three tables out of that, as in:

10.0 1 a 2
10.4 3 a 2
---
10.2 2 b 2
10.6 4 b 2
---
10.8 4 c 10
11.0 4 c 20

... which could then be plotted 'separately' - but I was wandering if gnuplot maybe had some internal facility for something like that?

Thanks in advance for any answers,
Cheers!

 

PS: Some useful links for me:

 

EDIT: just wanted to post a link to a script with which I'm getting close to visualizing the data the way I wanted to:

basic-labels.png

I'm kinda wanting to treat the labels (with the added 'points' as rectagle backgrounds) as nodes in graphviz or in TikZ, and set up those nice connection lines between them - but even this already helps me much :) Note that this is the wxt output - other terminals like png or pdfcairo will have a completely messed up rendering of boxes/labels (and would need to be tuned by hand).

Community
  • 1
  • 1
sdaau
  • 36,975
  • 46
  • 198
  • 278

2 Answers2

3

You could use awk for that. I don't know if I would call that "some internal facility" of gnuplot, but I think it does what you want it to do:

With a data file Data.csv:

10.0 1 a 2
10.2 2 b 2
10.4 3 a 2
10.6 4 b 2
10.8 4 c 10
11.0 4 c 20

plot the data with

plot "<awk '{if($3 == \"a\") print $1,$2}' Data.csv" u ($1 - 10):2 w lp, \
     "<awk '{if($3 == \"b\") print $1,$2}' Data.csv" u ($1 - 10):2 w lp, \
     "<awk '{if($3 == \"c\") print $1,$2}' Data.csv" u ($1 - 10):2 w lp

Note the \" to escape the script parser ^^.
As for plot style issues you can make use of the full spectrum gnuplot has to offer.

Woltan
  • 13,723
  • 15
  • 78
  • 104
  • 1
    Many thanks for that @Woltan - another way would be to call shell with something like `!grep "a " inline.dat > a.dat `; and then use respective tables for individual display; but I'd consider the `gnuplot` ternary operator use as in [#7525417](http://stackoverflow.com/questions/7522147/can-gnuplot-split-data/7525417#7525417) to be the 'native' way to do it... Cheers! – sdaau Sep 23 '11 at 08:43
  • 1
    @sdaau It seems that there are many solutions to this "problem". And as always its a matter of taste which one you choose. But I find it a little awkward to produce invalid numbers to not plot points. But then again its a matter of taste. ^^ – Woltan Sep 23 '11 at 08:47
  • you're right; but when I said "native", I merely meant that there are no system/shell calls involved with that solution (even if it turns out it is not the optimal strategy) ... Cheers! – sdaau Sep 23 '11 at 08:54
3

It is possible. Gnuplot has a ternary operator like in C. Gnuplot also will ignore undefined expressions, such as logarithms of negative numbers or dividing by zero. Putting those together, you can plot only those lines that satisfy some particular condition by producing invalid numbers for those that fail to satisfy the condition. Simplifying a bit from the question, the approach looks like this:

plot "inline.dat" using (strcol(3) eq 'a' ? $1 : 1/0):2
Michael J. Barber
  • 24,518
  • 9
  • 68
  • 88
  • Just a note: a conditional plot with `1/0` will interfere with `lines` or `linespoints` rendering; in which case, an extern program must be called - discussed in http://stackoverflow.com/questions/11187691/gnuplot-conditional-plotting-2-15-2-1-0-with-lines – sdaau Jul 10 '13 at 21:36
  • @sdaau, there is (or was) no need for an external program for conditional plotting with `lines` or `linespoints`. Even not for gnuplot 4.4 or 4.6. There is a simple workaround https://stackoverflow.com/a/54475591/7295599 – theozh Feb 28 '19 at 20:05