FlyBob
FlyBob

Reputation: 69

Histogram Gnuplot mixing Clustered/Stacked

I have a histogram consisiting in 6 columns. I would like to clustered them in pairs to have two clustered group made of two stacked colums. I almost done it, except that the legend is has double the entries that I want and that the graph is not centered

set terminal epslatex standalone color size 4.0in,3.0in background rgb "white"
set output 'massFlowSection.tex'

set xtics("ex1" 1, "ex2" 2, "ex3" 3)
#set yrange [0:100]

set style fill solid border -1
#set key invert
#set grid

num_of_ksptypes=2
set boxwidth 0.5/num_of_ksptypes
dx=0.5/num_of_ksptypes
offset=-0.12

plot 'data1.dat' using ($1+offset):($2+$3+$4) title "par3"  with boxes, \
         ''                   using ($1+offset):($3+$4) title "par2" with boxes, \
         ''                   using ($1+offset):($4) title "par1" with boxes, \
         'data2.dat' using ($1+offset+dx):($2+$3+$4) title "par3"  with boxes, \
         ''                   using ($1+offset+dx):($2+$3) title "par2" with boxes, \
         ''                   using ($1+offset+dx):($4)  title "par1" with boxes 

The entry data are file data1.dat

area  par3     par2    par1  
1     0.0078   0.0211  0     
2     0.0139   0.0302  0    
3     0.0169   0       0.119 

and file data2.dat

nr  par3     par2    par1 
1   0.0083   0.0233  0     
2   0.0151   0.0302  0    
3   0.0173   0       0.211  

This is the result

enter image description here

Upvotes: 1

Views: 212

Answers (1)

theozh
theozh

Reputation: 26198

The following might be a starting point for further tweaking. I tried to keep it general, such that you can easily add more columns or rows.

In your code you are summing up the column values "manually" $2+$3+$4. There are certainly ways to sum up columns "automatically". But, I allowed myself to transpose your data, because I found it easier. Let me know if you can live with it. Since gnuplot has no transpose function, you either have to implement it yourself or use external software. The latter, I usually try to avoid because of platform-independence. I guess there is also a way to do the same plot for your original data.

I prefer the plotting style with boxxyerror instead of with boxes which is always starting from zero. Actually, the last plot command is plotting nothing but just getting somehow the legend. This is still suboptimal. A additional declaration could be added which tells you which stack is Data1 and which is Data2.

Code:

### Histogram stacked and grouped
reset session

$Data1 <<EOD
area  "ex 1"  "ex 2"  "ex 3"
par1  0       0       0.119
par2  0.0211  0.0302  0
par3  0.0078  0.0139  0.0169
EOD

$Data2 <<EOD
nr    "ex 1"  "ex 2"  "ex 3"
par1  0       0       0.211
par2  0.0233  0.0302  0
par3  0.0083  0.0151  0.0173
EOD

set key top left
set style fill solid border -1

Cols = 3
Groups = 2
GroupGap = 0.2
BoxScale = 0.9
BoxWidth = (1.0-GroupGap)/Groups
Offset(g,i) = i-1.5+GroupGap/2.0 + BoxWidth/2 +(g-1)*BoxWidth

myXtic(i) = columnhead(i)
BoxL(g,i) = Offset(g,i)-BoxWidth/2.*BoxScale
BoxR(g,i) = Offset(g,i)+BoxWidth/2.*BoxScale
set xrange [0.5:Cols+0.5]

array myPalette[6] = [0xff0000, 0x00ff00, 0x0000ff, 0xffaaaa, 0xaaffaa, 0xaaaaff]
myColors(n) = myPalette[n+1+(g-1)*3]

set table $Legend
    plot $Data1 u (strcol(1)) w table
unset table

plot \
    for [i=2:Cols+1] $Data1 u (g=1,i-1):(int($0)?sum:sum=0):\
      (BoxL(g,i)):(BoxR(g,i)):(sum):(sum=sum+column(i)):(myColors($0)) \
      skip 1 w boxxy lc rgb var not, \
    for [i=2:Cols+1] $Data2 u (g=2,i-1):(int($0)?sum:sum=0):\
      (BoxL(g,i)):(BoxR(g,i)):(sum):(sum=sum+column(i)):(myColors($0)) \
      skip 1 w boxxy lc rgb var not, \
    for [i=2:|$Legend|] $Data1 u (g=1,i-1):(NaN):(myColors(i-2)): \
      xtic(columnhead(i)) w boxes lc rgb var ti word($Legend[i],1)
### end of code

Result:

enter image description here

Upvotes: 1

Related Questions