Search code examples
gnuplothistogram

gnuplot: How to put sum above bars with clustered stacked histograms


Thanks to the question gnuplot rowstacked histogram: how to put sum above bars and its answer, I learned how to add the sum of stacked histograms above their bars. However, I can't figure out how to achieve this with stacked histograms that are clustered. As shown in the below code, I can get the sum which seem to be placed at the right y coordinates.

Unfortunately, I don't know how to change the x coordinates for the second and third clusters, so they end up overlapping the first cluster's sum labels. What do I need to do to change the x coordinates of the sums so that they appear over the correct bars?


set term png size 1200, 500
set output "graph.png"
set datafile separator ","

set boxwidth 0.5
set style fill solid
set style data histograms
set style histogram rowstack

set offset -1.3,-0.3,100,0
set yrange [*:*] noextend
set xrange [*:*] noextend

set key outside
set key right top
set ylabel "Time (ms)"
set xtics font ", 10"

plot newhistogram at 0, "a.csv" u 2:xtic(1) t "Download" lc 1, \
    '' u 3:xtic(1) t "Transfer" lc 2, \
    '' u 4:xtic(1) t "Return" lc 3, \
    '' u 5:xtic(1) t "Processing" lc 4, \
    '' u 6:xtic(1) t "Wait" lc 5, \
    '' u 7:xtic(1) t "Overhead" lc 6, \
    '' u 0:($2+$3+$4+$5+$6+$7):(sprintf('%d', $2+$3+$4+$5+$6+$7)) not with labels offset 0,0.7, \
  newhistogram at 3, "b.csv" u 2:xtic(1) t "" lc 1,\
    for [i=3:7] '' u i:xtic(1) t "" lc (i - 1), \
    '' u 0:($2+$3+$4+$5+$6+$7):(sprintf('%d', $2+$3+$4+$5+$6+$7)) not with labels offset 0,0.7, \
  newhistogram at 6, "c.csv" u 2:xtic(1) t "" lc 1,\
    for [i=3:7] '' u i:xtic(1) t "" lc (i - 1), \
    '' u 0:($2+$3+$4+$5+$6+$7):(sprintf('%d', $2+$3+$4+$5+$6+$7)) not with labels offset 0,0.7

Data files:

  • a.csv

    Device,Download,Transfer,Return,Processing,Wait,Overhead
    Find X2 Pro,350,0,0,287,1,24
    OnePlus 8,350,29,19,410,30,138
    
  • b.csv

    Device,Download,Transfer,Return,Processing,Wait,Overhead
    Find X2 Pro,350,0,0,293,1,26
    Pixel 6,350,81,21,216,100,228
    
  • c.csv

    Device,Download,Transfer,Return,Processing,Wait,Overhead
    Pixel 6,350,0,0,436,2,43
    Pixel 3,350,140,46,187,52,206
    

gnplot output


Solution

  • Here I tried to clean up and simplify your script. I included the data as datablocks, so it is simply copy & paste & run. Check help sum, help columnheader... I hope the rest is self-explaining.

    Script:

    ### rowstacked histogram with total above bars
    reset session
    
    $DataA <<EOD
    Device,Download,Transfer,Return,Processing,Wait,Overhead
    Find X2 Pro,350,0,0,287,1,24
    OnePlus 8,350,29,19,410,30,138
    EOD
    
    $DataB <<EOD
    Device,Download,Transfer,Return,Processing,Wait,Overhead
    Find X2 Pro,350,0,0,293,1,26
    Pixel 6,350,81,21,216,100,228
    EOD
    
    $DataC <<EOD
    Device,Download,Transfer,Return,Processing,Wait,Overhead
    Pixel 6,350,0,0,436,2,43
    Pixel 3,350,140,46,187,52,206
    EOD
    
    set datafile separator ","
    set boxwidth 0.5
    set style fill solid
    set style data histograms
    set style histogram rowstack
    
    set offset -1.3,-0.3,100,0
    set xrange [0:]
    set xtics font ", 10" right rotate by 45
    set yrange [0:*]
    set ylabel "Time (ms)"
    set key outside right top noautotitle
    
    mySum(n) = sum [_i=2:7] column(_i)
    
    plot newhistogram at 2, \
             for [i=2:7] $DataA u i:xtic(1) ti columnheader(i) lc i-1, \
             '' u ($0+1):(total=mySum(0)):(sprintf('%d', total)) w labels offset 0,0.7, \
         newhistogram at 4,\
             for [i=2:7] $DataB u i:xtic(1) lc i-1, \
             '' u ($0+4):(total=mySum(0)):(sprintf('%d', total)) w labels offset 0,0.7, \
         newhistogram at 7, \
             for [i=2:7] $DataC u i:xtic(1) lc i-1, \
             '' u ($0+7):(total=mySum(0)):(sprintf('%d', total)) w labels offset 0,0.7, \
    ### end of script
    

    Result:

    enter image description here