13

I would like to plot results of classification and mark true classes. So, basically what I need is to assign a color for each point base on value in a string column.

dataset looks like this:

5.1 3.5 1.4 0.2 Iris-setosa

I ended up with script following solution (thanks to the answer in here: How to make points one color when a third column equals zero, and another color otherwise, in Gnuplot?)

set palette model RGB defined (0 "red",1 "blue", 2 "green")
plot 'iris.data' using 1:2:5 notitle with points pt 2 palette

in the original dataset I replaced string labels with numbers, because I don't know how to work with strings in gnuplot. Is there a way how to map string to colors?

Currently the output looks like this: gnuplot coloring points

However I don't like the gradient palette because it doesn't make sense in this case. I would prefer normal legend with a single color and name of the class. Any idea how to do that?

1
  • I have the same question. It would be great if the gnuplot palette accepted strings instead of just integers. I don't think it does. Commented Jan 25, 2013 at 8:57

4 Answers 4

7

A way how you could do that is by using awk.

Using a data file Data.csv:

5.4452 4.6816 blue
1.2079 9.4082 red
7.4732 6.5507 red
2.3329 8.2996 red
3.4535 2.1937 green
1.7909 2.5173 green
2.5383 7.9700 blue

and this script:

set pointsize 3
plot "< awk '{if($3 == \"red\") print}' Data.csv" u 1:2 t "red" w p pt 2, \
     "< awk '{if($3 == \"green\") print}' Data.csv" u 1:2 t "green" w p pt 2, \
     "< awk '{if($3 == \"blue\") print}' Data.csv" u 1:2 t "blue" w p pt 2

you get this plot:

enter image description here

What awk does is simply check the third parameter of the data file and only print the line if it has some value: like red or blue.

You would also get rid of the palette with the gradient.

The script could be further improved by using gnuplot iterations.

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

6 Comments

thanks, I'm pretty new to gnuplot and the syntax is quite confusing to me. using awk is quite convenient
@Tombart If you have any specific questions about the syntax I used in the example, let me know and I will elaborate on it.
here the $3 is the value of third column but it not specified what is the delimiter? will it be automatically taken as <TAB>?
@damned I didn't find any documentation on that but it appears that you can use any combination of tabs and spaces to separate your columns. Maybe someone else can back that up...
I explicitly added <TAB> separator and then it worked fine: awk -F $'\t' '{if($3 == \"red\") print}' ".
|
5

Mapping strings to colors or to palette indices can be done natively in gnuplot, the key is to use stringcolumn() and a user-defined mapping function.

Here is an example using a palette:

#!/usr/bin/gnuplot -persist

# define a palette with an exact number of colors
set palette maxcolors 3
set palette model RGB defined ( \
  0 "red", \
  1 "blue", \
  2 "green")

# Define palette labels, the range matches the number of colors defined above
set cbrange [0:3]
set cbtics offset 0,+4 ( \
  'color1' 0, \
  'color2' 1, \
  'color3' 2, \
  '' 3)

# define a function to map strings to palette indices
map_color(string) = ( \
  string eq 'color1' ? 0 : \
  string eq 'color2' ? 1 : \
  string eq 'color3' ? 2 : \
  3)

plot '-' using 1:2:(map_color(stringcolumn(3))) notitle with points pt 2 palette
5.4452 4.6816 color1
1.2079 9.4082 color2
7.4732 6.5507 color2
2.3329 8.2996 color2
3.4535 2.1937 color3
1.7909 2.5173 color3
2.5383 7.9700 color1
EOF

enter image description here

A similar approach can be taken to map to colors directly:

#!/usr/bin/gnuplot -persist

# define a function to map strings to palette indices
map_color(string) = ( \
  string eq 'color1' ? 0xff0000 : \
  string eq 'color2' ? 0x0000ff : \
  string eq 'color3' ? 0x00ff00 : \
  0x000000)

plot '-' using 1:2:(map_color(stringcolumn(3))) notitle with points pt 2 lc rgbcolor variable
5.4452 4.6816 color1
1.2079 9.4082 color2
7.4732 6.5507 color2
2.3329 8.2996 color2
3.4535 2.1937 color3
1.7909 2.5173 color3
2.5383 7.9700 color1
EOF

1 Comment

Awesome, this does exactly what I needed! Gnuplot is really amazing. If only it weren't so incredibly opaque...
3

A color palette can be used to get any point color (for individual points)

plot file using 1:2:3 with points palette

Now set up a palette that gives you the desired color scale. You can set the palette to compute the color for example using the HSV color model or have a look at the the gnuplot demos website.

Just for completeness, have a look at the last example on gnuplot pm3d colors demo page:

color bar with distinct colors in gnuplot

theta(x) = x<0 ? 0 : 1
r(x) = 4*x*(1-theta(x-0.25))
g(x) = 0.5*theta(x-0.25)*(1-theta(x-0.5))
b(x) = x
set palette model RGB functions r(gray),g(gray),b(gray)
set title "set palette model RGB functions\n4*x*(1-theta(x-0.25)), 0.5*theta(x-0.25)*(1-theta(x-0.5)), x"
splot f(x)enter code here

Comments

0

As colors are hex numbers, then we can take some starting color and some increasing step, for example I took in bash

FIRST_COLOR=0xB97900
ADDING_COLOR=0x1F541E

Then, in for cycle, for lines I used hex numbers addition

for ((i = 1 ;  i <=  $some_number ; i++ ));
do
 FIRST_COLOR=$(( $FIRST_COLOR + $ADDING_COLOR ))
 x=`printf "0x%X\n" $FIRST_COLOR`
 echo "set style line $i lc rgb '$x' lt 1 lw 1 pt $i ps 1" > some_file
done

so, we can have in some_file as many colors as want, though if the initial number and increment are poorly selected, then the colors are difficult to distinguish, although a lot depends on the quality of the screen.

Same can be done, of course, for points.

Hope, helps somebody.

4 Comments

in principle nice idea, however, this doesn't answer the question. OP has a column with strings in the data file and want's to get from a specific string to a specific color. By the way, your script doesn't look like a valid gnuplot script.
It is part of working script on debian. Of course there are additional strings, but I wrote only that part which gives colors. Other string easy echoed in similar way. I wanted to show method which generates colors in "any" amount.
well, I understand your principle and I assume it works somehow, but how does your answer fit to OP's question?
Somehow my script possibly will not work in very exotic ecosystem. As to question, then each decimal number is in same time hex and my,"in principle nice idea", which you kindly had estimated, gives possibility to map each value of string not to one, but to "infinite" possible colors. Generally to, so called, pseudo random sequence.

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.