labelgnuplothistogramstacked

How to draw rowstacked histogram in gnuplot with value labels in each bar


I want to draw a rowstacked histogram. The following is what I have so far enter image description here.

I have used the code below

reset
set bmargin 10
set lmargin 20
set rmargin 16
set tmargin 7
show margin  

set title "" font "Verdana,27"
show title
set grid

set xlabel offset 0,-5 font "Verdana,25"
set xlabel "Number of Cores"
show xlabel
set xtics font "Verdana,18"

set ylabel offset -4,0 font "Verdana,25"
set ylabel "Time (%)"
show ylabel
set yrange [0:130]
set ytics font "Verdana,18"  
set ytics (0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)

set style data histogram
set style histogram rowstacked title offset 0,3
set style fill solid border lt -1
set boxwidth 0.9

set key right
set key font "Verdana,17"
set key autotitle columnheader horizontal


plot newhistogram '{/=22 1-Core}', \
        for [i=2:5] 'base_vs_FHA_speedup_1core.dat' using i:xtic(1), \
     newhistogram '{/=22 2-Cores}' lt 1, \
        for [i=2:5] 'base_vs_FHA_speedup_2core.dat' using i:xtic(1) notitle, \
     newhistogram '{/=22 4-Cores}' lt 1, \
        for [i=2:5] 'base_vs_FHA_speedup_4core.dat' using i:xtic(1) notitle, \
     newhistogram '{/=22 8-Cores}' lt 1, \
        for [i=2:5] 'base_vs_FHA_speedup_8core.dat' using i:xtic(1) notitle

I have 4 different data files with sample data like this

base_vs_FHA_1core.dat

Configuration col1 col2 col3 col4 col5

Base 5 50 40.5 4.5
FHA 5 16 38 5 1.54x

base_vs_FHA_2core.dat

Base 9.3 47 37.3 6.3
FHA 9.3 15 34.3 6.3 1.54x

base_vs_FHA_4core.dat

Base 18 41 33.9 7.06
FHA 16.6 13.07 30.7 7.4 1.47x

base_vs_FHA_8core.dat

Base 27.7 34.3 28.3 9.6
FHA 28.3 11.45 25.3 9.6 1.34x

I want to have each bar in the histogram labeled with the corresponding value and the value of the last column on the top of the second histogram in each pair. How can I achieve this?

Can I merge all the 4 files and achieve the same goal?


Solution

  • You can merge all 4 files in one file. I would recommend a separation with two empty lines, because with this, you can easily address the (sub)datablocks via index, check help index.

    For the labels you can make a double loop, one for the (sub)datablocks and one for the columns. You have to sum up the columns (check help sum) to calculate the y-position of the label (i.e. center of the histogram element). The x-position of the labels is special for the first dataset (since only this has a columnheader), this is taken into account with (i*3+$0-(i==0)), i.e. i==0 will return 1 if i equals 0, and 0 otherwise.

    Instead of setting a large fontsize many times you might want to set it in the terminal, e.g. something like: set term pngcairo font ",17".

    Find below a minimized example as a starting point for further optimization.

    Script:

    ### rowstacked histogram with numbers in corresponding boxes
    reset session
    
    $Data <<EOD
    # base_vs_FHA_1core.dat
    col1 col2 col3 col4 col5
    Base 5 50 40.5 4.5
    FHA  5 16 38 5 1.54x
    
    
    # base_vs_FHA_2core.dat
    Base 9.3 47 37.3 6.3
    FHA  9.3 15 34.3 6.3 1.54x
    
    
    # base_vs_FHA_4core.dat
    Base 18   41    33.9 7.06
    FHA  16.6 13.07 30.7 7.4  1.47x
    
    
    # base_vs_FHA_8core.dat
    Base 27.7 34.3  28.3 9.6
    FHA  28.3 11.45 25.3 9.6 1.34x
    EOD
    
    set xlabel "Number of Cores"
    set ylabel "Time (%)"
    set yrange [0:130]
    set ytics 0, 10, 100
    set grid
    
    set style data histogram
    set style histogram rowstacked title
    set style fill solid 0.5 border lt -1
    set boxwidth 0.9
    set key top left noautotitle horizontal
    
    N = 5   # number of last data column
    
    plot newhistogram '1-Core' at 0, \
            for [i=2:N] $Data index 0 u i:xtic(1) ti columnheader, \
         newhistogram '2-Cores' lt 1 at 3, \
            for [i=2:N] '' index 1 u i:xtic(1), \
         newhistogram '4-Cores' lt 1 at 6, \
            for [i=2:N] '' index 2 u i:xtic(1), \
         newhistogram '8-Cores' lt 1 at 9, \
            for [i=2:N] '' index 3 u i:xtic(1), \
        for [i=0:3] for [j=2:N] '' index i u (i*3+$0-(i==0)): \
            ((sum [k=2:j] column(k))-column(j)*0.5):j w labels
    ### end of script
    

    Result:

    enter image description here