How to make a groupedbar plot with several stacked bars

It’s really hard to explain in words what I would like to do, so here is a picture:

The black lines represent “levels” - each level has a stacked bar in it.

I know how this was done in Matlab, I just need help translating it to Julia. Say for example that for a particular x value I have 3 levels, and 2 different values in each level, then to plot this you plot the bar as a vector, but you specify the colors in the bar for each level. You also don’t show the legend, and just create the legend yourself, since otherwise Matlab (and, I imagine, Plots) get confused.

Assuming I use groupedbar from StatsPlots to do this, what I would like to know is:

  • How to specify colours for each segment of a bar in the graph
  • How to make a custom legend (i.e. a text box) with square boxes for colours next to the legend entry.

Matlab code is below:

% sort the generation matrix by technology

logInd_TN = ismember(p.plant.portfolio(:,1),[1]);

logInd_ST = ismember(p.plant.portfolio(:,1),[2:14,33:42,50]);

logInd_ST_coal = ismember(p.plant.portfolio(:,1),[5:7,36:38]);

logInd_ST_lignite = ismember(p.plant.portfolio(:,1),[2:4,33:35]);

logInd_ST_oil = ismember(p.plant.portfolio(:,1),[11:12,41]);

logInd_ST_gas = ismember(p.plant.portfolio(:,1),[8:9,39,50]);

logInd_CCGT = ismember(p.plant.portfolio(:,1),[15:18,43:45]);

logInd_CCGT_small = ismember(p.plant.portfolio(:,1),[15:18,43:45]) & p.plant.portfolio(:,4) <= 150; %

logInd_CCGT_large = ismember(p.plant.portfolio(:,1),[15:18,43:45]) & p.plant.portfolio(:,4) > 150; %

logInd_GT = ismember(p.plant.portfolio(:,1),[19:25,46:49,51]);

logInd_IC = ismember(p.plant.portfolio(:,1),[26:32]);

reserves_prob = [];

for rr = 1:u.plant.reservelevels

  reserves_prob = [reserves_prob;












currentFolder = pwd;

fpath = [strcat(currentFolder,'\',i.resultstring)]; % it is saved in the result folder

figure('units','normalized','outerposition',[0 0 1 1]) % make the figure full screen

h1 = bar(reserves_prob','stacked','BarWidth',1,'EdgeColor','none','EdgeAlpha',0); hold on

% set(h,'EdgeColor','black');

aa = sum(logInd_TN);

bb = sum(logInd_ST);

cc = sum(logInd_CCGT);

dd = sum(logInd_GT)*2;

ee = sum(logInd_IC);

ff = 1;

gg = 1;

rr = aa+bb+cc+dd+ee+ff+gg;

for ll = 1:u.plant.reservelevels







set(h1((ll-1)*rr+aa+bb+cc+dd+ee+ff+1:(ll-1)*rr+aa+bb+cc+dd+ee+ff+gg),'FaceColor',[0.5 0.5 0.5]);



annotation('textbox','Position',[0.8 0.85 0.08 0.03],'String','RR shed','Color',[0.5 0.5 0.5],'FontSize',12,'FontWeight','bold');

annotation('textbox','Position',[0.8 0.82 0.08 0.03],'String','RES','Color',[255,127,0]/256,'FontSize',12,'FontWeight','bold');

annotation('textbox','Position',[0.8 0.79 0.08 0.03],'String','IC     (NSR)','Color','m','FontSize',12,'FontWeight','bold');

annotation('textbox','Position',[0.8 0.76 0.08 0.03],'String','GT    (NSR)','Color','c','FontSize',12,'FontWeight','bold');

annotation('textbox','Position',[0.8 0.73 0.08 0.03],'String','CCGT (SR)','Color','g','FontSize',12,'FontWeight','bold');

annotation('textbox','Position',[0.8 0.70 0.08 0.03],'String','ST       (SR)','Color','r','FontSize',12,'FontWeight','bold');

annotation('textbox','Position',[0.8 0.67 0.08 0.03],'String','TN       (SR)','Color','b','FontSize',12,'FontWeight','bold');

 for tt = 1:s.period

  for ss = 1:s.reserve

    i_opt = ceil(tt/(s.solopt));

    if rem(tt,s.solopt) == 0; t_opt = s.solopt; else t_opt = rem(tt,s.solopt); end

    RR_up(tt,:) = sum(p.reserve.levels(i_opt,:,t_opt,1,:,r.scenario_branch),5)';                      % upward reserves requirement [MW]

    RR_down(tt,:) = sum(p.reserve.levels(i_opt,:,t_opt,2,:,r.scenario_branch),5)';                    % downward reserves requirement [MW]



 for ll = 1:u.plant.reservelevels




str1 = sprintf([{2,2} '-RR-FINAL          ' i.resultstring]);

str2 = sprintf('RSF: %g h  RSR: %g h  RPCD: %g h  RPF: %g h  PH: %g h  SULT: %g  RR option: %g  RR levels: %g  Tol.: %g %%',u.time.reservesfreq,u.time.RRresolution,u.time.reservescd,u.time.opt,u.time.opt+u.time.optseq,u.plant.suleadtimes,u.plant.reserve,u.plant.reservelevels,round(u.solver.tol,2));


% ax = gca; ax.XTick = [1,6,12,18,24]; get(gca,'XTick'); set(gca,'FontSize',12)

ylabel('Operational reserves (MW)','FontSize',12)

xlabel(['Timestep (' num2str(s.timestep) ' h)'],'FontSize',12)

The groupedbar recipe in StatsPlots.jl should do the trick.

Thanks, but I was more wondering how to specify colours and make the custom legend.

This is based on the Plots.jl library, so the same way you do there.

using StatsPlots

m = rand(5,3)

    label = ["first thing" "second thing" "third thing"],
    color = [:green :lightgrey :purple] # can also use Colors.jl or ColorBrewer.jl

Note: I’m on mobile so I can’t guarantee that works, but something like that. Check out the docs for Plots.jl. each individual set (color) is called a “series”.

1 Like

I think I wasn’t clear with what I wanted to do. In any case, here’s my code in it’s entirety to show what I ended up doing. It’s not a minimal working example, it’s just there as guidance for anyone else who wants to try doing this.

My main things to solve my problems were:

  1. The series colour repeats, so if you have 30 series and 6 colours then you will get 6 colours repeated 5 times in the order you specify
  2. I used an empty plot to make a custom legend

You can find an example picture at the bottom.

GRP = gep.GRP; P = gep.P; T = gep.T; L⁺ = gep.L⁺
    nRP = length(GRP) # Number of reserve providers
    nL = length(L⁺)

    rL⁺ = gep[:rL⁺].data
    curtL⁺ = gep[:curtL⁺].data
    LSL⁺ = reshape(gep[:LSL⁺].data, (1,size(gep[:LSL⁺])...))
    reserves = cat(rL⁺, curtL⁺, LSL⁺; dims=1)
    y = fill(0.0, length(L⁺)*length(GRP), length(P), length(T))
    y2 = fill(0.0, length(L⁺), length(P), length(T)) # Reserve level line plots
    for p = P
        for t = T
            for l = L⁺
                for g = 1:nRP
                    y[(l-1)*nRP+g,p,t] = reserves[g,l,p,t]
            for l = L⁺[2:end]
                y2[l,p,t] = y2[l-1,p,t] + sum(reserves[:,l,p,t])

    seriescolor = [:red :blue :orange :yellow :green :purple]

    # Shorten depending on number of reserve providers
    seriescolor = seriescolor[:,1:nRP]

    # Plot the differentiated reserves
    p1 = groupedbar(y[:,p,:]', legend=:none, bar_width=1, bar_position=:stack, seriescolor=seriescolor, xlabel="Timestep", ylabel="Reserves (MW)", linewidth=0)

    # Plot the reserve level lines
    plot!(p1, T, y2[:,p,:]', seriescolor=:black, linewidth=2)

    # Do some hacky shit for the legend
    empty = fill(0.0, 1, nRP)
    p2 = plot(1, empty, lab=GRP, legend=:best, grid=false, showaxis=false, ylims=(1,2), seriescolor=seriescolor, linewidth=6)

    # Plot everyting
    l = @layout [a{0.8w} b{0.2w}]
    plot(p1, p2, layout=l)