Rsaesha
Rsaesha

Reputation: 1114

Different coloured bars in gnuplot bar chart?

I have a very simple dataset:

Critical 2
High 18
Medium 5
Low 14

Creating a bar chart in gnuplot out of this dataset is easy, but all the bars are the same colour. I want to have it so that Critical is black, high is red, etc, but there seem to be hardly any online tutorials for doing this.

Can anyone point me in the right direction?

Upvotes: 6

Views: 5666

Answers (2)

Christoph
Christoph

Reputation: 48440

Here is how you can do this using the linecolor variable option.

If you know, that the lines are always in the same, known order, you can use the row number (zeroth column, $0) as linetype index:

set style fill solid noborder
set linetype 1 lc rgb 'black'
set linetype 2 lc rgb 'red'
set linetype 3 lc rgb 'yellow'
set linetype 4 lc rgb 'green'

set yrange [0:*]
unset key
plot 'alerts.txt' using 0:2:($0+1):xtic(1) with boxes linecolor variable

If the order may vary, you can use a gnuplot-style indexing function, which determines the index of the warning level from a string with space-separated words:

alerts = 'Critical High Medium Low'
index(s) = words(substr(alerts, 0, strstrt(alerts, s)-1)) + 1

set style fill solid noborder
set linetype 1 lc rgb 'black'
set linetype 2 lc rgb 'red'
set linetype 3 lc rgb 'yellow'
set linetype 4 lc rgb 'green'

set yrange [0:*]
unset key
plot 'alerts.txt' using 0:2:(index(strcol(1))):xtic(1) with boxes linecolor variable

enter image description here

Upvotes: 3

mgilson
mgilson

Reputation: 310287

set xrange [-.5:3.5]
set yrange [0:]
set style fill solid
plot "<sed 'G;G' test.dat" i 0 u (column(-2)):2:xtic(1) w boxes ti "Critical" lc rgb "black",\
     "<sed 'G;G' test.dat" i 1 u (column(-2)):2:xtic(1) w boxes ti "High" lc rgb "red" ,\
     "<sed 'G;G' test.dat" i 2 u (column(-2)):2:xtic(1) w boxes ti "Medium" lc rgb "green",\
     "<sed 'G;G' test.dat" i 3 u (column(-2)):2:xtic(1) w boxes ti "Low" lc rgb "blue"

This takes sed and triple spaces your file so that gnuplot sees each line as a different dataset (or "index"). You can plot each index separately using index <number> or i <number> for short as I have done. Also, the index number is available as column(-2) which is how we get the boxes properly spaced.

Possibly a slightly more clean (gnuplot only) solution is using filters:

set xrange [-.5:3.5]
set yrange [0:]
set style fill solid
CRITROW(x,y)=(x eq "Critical") ? y:1/0
HIGHROW(x,y)=(x eq "High") ? y:1/0
MIDROW(x,y) =(x eq "Medium") ? y:1/0
LOWROW(x,y) =(x eq "Low") ? y:1/0
plot 'test.dat' u ($0):(CRITROW(stringcolumn(1),$2)):xtic(1) w boxes lc rgb "black" ti "Critical" ,\
     '' u ($0):(HIGHROW(stringcolumn(1),$2)):xtic(1) w boxes lc rgb "red" ti "High" ,\
     '' u ($0):(MIDROW(stringcolumn(1),$2)):xtic(1) w boxes lc rgb "green" ti "Medium" ,\
     '' u ($0):(LOWROW(stringcolumn(1),$2)):xtic(1) w boxes lc rgb "blue" ti "Low"

This solution also doesn't depend on any particular ordering in your datafile (which is why I prefer it slightly to the other solution. We accomplish the spacing here with column(0) (or $0) which is the record number in the dataset (in this case, the line number).

Upvotes: 5

Related Questions