How to create a rowstacked and clustered bar chart in gnuplot?
Yet another gnuplot bar chart (histogram) question. Starting from a flat list (could be any order), I want to create a normalized rowstacked and clustered bar chart.
-
There is a similar question with an answer, however, with no response of the OP and the suggestion in the answer does not cover my case.
-
Another question to the same topic, however, with answers without the desired solution.
Looking at the gnuplot homepage, gnuplot offers rowstacked histograms and clustered histograms. But apparently, no rowstacked and clustered histogram. Although, there is newhistogram
, which however, places a separate bar chart on the x-axis next to the previous one. Not interlaced as I would like it to be.
So, if I use:
set style histogram rowstacked clustered
, the bar chart will be just clustered (see first graph below)set style histogram clustered rowstacked
, the bar chart will continue stacking (see second graph below)
Apparently, the later keyword overwrites the former one. Furthermore, I thought I could use simply set style histogram rowstacked
and shift the first bar chart a bit to the left and the second one a bit to the right and use thinner bars, but apparently gnuplot doesn't allow something like:
plot for [COL=2:4] $Histo ($0-0.3):COL:xtic(1) index 0, \
for [COL=2:4] '' ($0+0.3):COL:xtic(1) index 1
This will result in an error: Too many columns in using specification
I know that in principle I could draw the bar chart from "scratch" with the plotting style with boxxyerror
, but why making things complicated if I maybe just overlooked a simple option?
Script:
### how to create a rowstacked AND clustered bar chart from a flat list
reset session
$Data <<EOD
# Mark Group Test Value
A Group1 Test1 23
B Group1 Test1 12
C Group1 Test1 14
A Group2 Test1 23
B Group2 Test1 9
C Group2 Test1 7
A Group1 Test2 11
B Group1 Test2 16
C Group1 Test2 19
A Group2 Test2 13
B Group2 Test2 24
C Group2 Test2 5
A Group1 Test3 4
B Group1 Test3 14
C Group1 Test3 17
A Group2 Test3 15
B Group2 Test3 8
C Group2 Test3 4
A Group1 Test4 10
B Group1 Test4 12
C Group1 Test4 16
A Group2 Test4 19
B Group2 Test4 20
C Group2 Test4 15
EOD
Marks = "A B C"
Groups = "Group1 Group2"
Tests = "Test1 Test2 Test3 Test4"
Mark(i) = word(Marks,i)
Group(i) = word(Groups,i)
Test(i) = word(Tests,i)
myFilter(col1,val1,col2,val2,col3,val3) = (strcol(col1) eq val1) && (strcol(col2) eq val2) && (strcol(col3) eq val3)
set print $Histo
do for [g=1:words(Groups)] {
print sprintf("# %s",Group(g))
print sprintf("X %s Sum",Marks)
do for [t=1:words(Tests)] {
Line = Test(t)
mySum = 0
do for [m=1:words(Marks)] {
value = 0
stats $Data u (myFilter(1,Mark(m),2,Group(g),3,Test(t)) ? value=column(4) : 0) nooutput
Line = Line.sprintf(" %g",value)
mySum = mySum + value
}
Line = Line.sprintf(" %g",mySum)
print Line
}
print ''; print '' # two empty lines
}
set print
print $Histo
set style data histogram
set style histogram clustered rowstacked # or: rowstacked clustered
set style fill solid 0.5
set yrange [0:]
set format y "%g%%"
set boxwidth 0.8
set grid y
set key noautotitle out title "Mark"
set offset 0.25,0.25,0,0
plot for [g=1:words(Groups)] for [col=2:words(Marks)+1] $Histo u \
(column(col)/(column(words(Marks)+2))*100):xtic(1) index g-1 ti columnheader(col)
### end of script
Result:
Datablock $Histo
:
# Group1
X A B C Sum
Test1 23 12 14 49
Test2 11 16 19 46
Test3 4 14 17 35
Test4 10 12 16 38
# Group2
X A B C Sum
Test1 23 9 7 39
Test2 13 24 5 42
Test3 15 8 4 27
Test4 19 20 15 54
set style histogram rowstacked clustered
set style histogram clustered rowstacked
Desired output should be something like this:
If I overlooked a simple solution which leads to the last plot, please let me know.
Comments
Post a Comment