2022-09-19

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

enter image description here

set style histogram clustered rowstacked

enter image description here

Desired output should be something like this:

enter image description here

If I overlooked a simple solution which leads to the last plot, please let me know.



No comments:

Post a Comment