Remove duplicate legend entries in PlotlyJS combined bar plot

Greetings:

I am vertically stacking two bar plots from PlotlyJS, which can be interpreted as a historical decomposition of output and the Solow residual over the business cycle into various shocks. The problem is that duplicated entries are generated in the legend. I believe using traces rather than plots may be the way to resolve this issue, but I am not sure how to implement it. The code I have is as follows:

time = range(Date(1966, 1, 1), step=Dates.Quarter(1), stop=Date(2021, 12, 31))
x = matopen("hist_dec.mat")
hist_dec = read(x, "hist_dec")
labels = ["Output", "Solow residual"]
figs = [PlotlyJS.plot() for _ in 1:2]
for i in 1:2
    hist_dec_i = hist_dec[i, :, :]
    # Transpose and drop measurement errors
    hist_dec_i = hist_dec_i'
    hist_dec_i = convert(DataFrames.DataFrame, hist_dec_i)
    hist_dec_i = hist_dec_i[!, 1:7]
    rename!(hist_dec_i, [:Consumption_tech, :Investment_tech, :Entry_tech, 
    :Intratemporal_preference, :Shopping_disutility, :Discount_factor, :Labor_supply])
    hist_dec_i[!, :date] = time
    long_df = DataFrames.stack(hist_dec_Y, Not([:date]), variable_name=:shock, value_name=:share)
    figs[i] = PlotlyJS.plot(long_df, kind="bar", x=:date, y=:share, color=:shock, Layout(title=labels[i],
        barmode="stack"))
end
fig_hist = [figs[1]; figs[2]]
relayout!(fig_hist, title_text="Historical decomposition", barmode="stack", color="shock")
display(fig_hist)
PlotlyJS.savefig(fig_hist, "fig_hist.pdf")

I attach the generated figure. Also, the information comes from a .mat file generated in another program, which I cannot attach here. Please let me know if it is necessary to provide the file in some other format.

I would need the .mat file to verify, but I believe you could do add something under

like
legend_on = [true, false]
then change this line

to

figs[i] = PlotlyJS.plot(long_df, kind="bar", x=:date, y=:share, color=:shock, Layout(title=labels[i],
        barmode="stack", showlegend=legend_on[i]))

Edit: actually, it’s somewhat more complicated…
Here is an MWE

using PlotlyJS
using Dates
using DataFrames

startyear = 2000
time = range(Date(startyear, 1, 1), step=Dates.Quarter(1), stop=Date(2021, 12, 31))
# x = matopen("hist_dec.mat")
# hist_dec = read(x, "hist_dec")
hist_dec = rand(-0.1:0.01:0.1, 2,length(time),8);

##
labels = ["Output" "Solow residual"]
legend_on = [true, false]
# figs = [PlotlyJS.plot() for _ in 1:2]
figs = Dict()

p = make_subplots(
    rows=2,
    cols=1,
    subplot_titles=labels,
    specs= [
        Spec(kind="bar") missing
        Spec(kind="bar") missing
    ]
);

for i in 1:2
    hist_dec_i = hist_dec[i, :, :]
    # Transpose and drop measurement errors
    # hist_dec_i = hist_dec_i'
    # hist_dec_i = convert(DataFrames.DataFrame, hist_dec_i)
    hist_dec_i = DataFrame(hist_dec_i, :auto)
    hist_dec_i = hist_dec_i[!, 1:7]
    rename!(hist_dec_i, [:Consumption_tech, :Investment_tech, :Entry_tech, 
    :Intratemporal_preference, :Shopping_disutility, :Discount_factor, :Labor_supply])
    hist_dec_i[!, :date] = time
    long_df = DataFrames.stack(hist_dec_i, Not([:date]), variable_name=:shock, value_name=:share)
    figs[i] = Plot(long_df, Layout(title=labels[i],barmode="stack"); 
                    kind="bar", x=:date, y=:share, color=:shock)

    for tr in figs[i].data
        tr.fields[:showlegend] = legend_on[i]
        add_trace!(p, tr, row=i, col=1)
    end
end

relayout!(p, title_text="Historical decomposition", barmode="stack", color="shock", yaxis_title="Share", xaxis_title="Date")
display(p)
1 Like

@Mario_Silva Any thoughts? Is this close to what you were thinking?

Hi!

Yes, I have just marked it as a solution. It works well, though slightly verbose.

1 Like

Great. Note that I had to change hist_dec_Y to hist_dec_i here:

The thing I couldn’t figure out was how to add axis labels to each subplot in the new version.