How to annotate a groupedbar-plot?

Hi there, I desperately try to label the individual bars of a groupedbar plot, as in
https://matplotlib.org/examples/api/barchart_demo.html

I took some code from a former post https://discourse.julialang.org/t/plots-bars-side-by-side/6655/12

and added

series_annotations = [string.(men), string.(women)]

resulting in:

using StatsPlots

men = [20, 35, 30, 35, 27]
women = [25, 32, 34, 20, 25]
std_men = [2, 3, 4, 1, 2]
std_women = [3, 5, 2, 3, 3]

groupedbar(
  ["G1", "G2", "G3", "G4", "G5"],
  [men women],
  yerr = [std_men std_women],
  series_annotations = [string.(men), string.(women)]
)

which gives a plot with misaligned annotations:
Screenshot from 2020-09-19 22-17-31

A second run results in a plot with the top cut off and an error message
“GKS: Rectangle definition is invalid in routine SET_VIEWPORT” .
Please help.

I’m using julia 1.5.1 with StatsPlots 0.14.13 on ubuntu 20.04.

Turns out my suggestion in the other thread wasn’t very good. I think there are two issues here:

  • Placement of annotations in the bar plot with GR backend - there’s an issue on this here
  • The Rectangle definition error - there are a bunch of issues related to this (see here), but none of these seem to describe this exact situation (although I’ll admit I haven’t read every single one in full). Might be worth opening another issue with this MWE.

Both issues seem to be GR related, so one thing to try might be just swapping out backends and seeing if that helps.

Changing to inspectdr and simplifying the labels to enhance visibility in the plot:

using StatsPlots
inspectdr()

men = [20, 35, 30, 35, 27]
women = [25, 32, 34, 20, 25]
std_men = [2, 3, 4, 1, 2]
std_women = [3, 5, 2, 3, 3]

groupedbar(
         ["G1", "G2", "G3", "G4", "G5"],
         [men women],
         yerr = [std_men std_women],
         series_annotations = string.([0,1,2,3,4,5,6,7,8,9])
       )

gives:

Even worse: G1, G2, … missing, only upper part of errorbars visible …

Changing to plotly():

Error showing value of type Plots.Plot{Plots.PlotlyBackend}:
ERROR: BoundsError: attempt to access 1-element Array{Float64,1} at index [2:3]
Stacktrace:
 [1] throw_boundserror(::Array{Float64,1}, ::Tuple{UnitRange{Int64}}) at ./abstractarray.jl:541
 [2] checkbounds at ./abstractarray.jl:506 [inlined]
 [3] getindex(::Array{Float64,1}, ::UnitRange{Int64}) at ./array.jl:815
 [4] plotly_series_segments(::Plots.Series, ::Dict{Symbol,Any}, ::Array{Float64,1}, ::Array{Float64,1}, ::Nothing, ::Tuple{Float64,Float64}) at /home/os/.julia/packages/Plots/GDtiZ/src/backends/plotly.jl:785
 [5] plotly_series(::Plots.Plot{Plots.PlotlyBackend}, ::Plots.Series) at /home/os/.julia/packages/Plots/GDtiZ/src/backends/plotly.jl:545
 [6] plotly_series(::Plots.Plot{Plots.PlotlyBackend}) at /home/os/.julia/packages/Plots/GDtiZ/src/backends/plotly.jl:863
 [7] plotly_series_json at /home/os/.julia/packages/Plots/GDtiZ/src/backends/plotly.jl:869 [inlined]
 [8] plotly_html_body(::Plots.Plot{Plots.PlotlyBackend}, ::Nothing) at /home/os/.julia/packages/Plots/GDtiZ/src/backends/plotly.jl:909
 [9] plotly_html_body at /home/os/.julia/packages/Plots/GDtiZ/src/backends/plotly.jl:904 [inlined]
 [10] html_body at /home/os/.julia/packages/Plots/GDtiZ/src/backends/plotly.jl:874 [inlined]
 [11] #standalone_html#347 at /home/os/.julia/packages/Plots/GDtiZ/src/backends/web.jl:7 [inlined]
 [12] write_temp_html(::Plots.Plot{Plots.PlotlyBackend}) at /home/os/.julia/packages/Plots/GDtiZ/src/backends/web.jl:36
 [13] standalone_html_window at /home/os/.julia/packages/Plots/GDtiZ/src/backends/web.jl:49 [inlined]
 [14] _display at /home/os/.julia/packages/Plots/GDtiZ/src/backends/plotly.jl:950 [inlined]
 [15] display(::Plots.PlotsDisplay, ::Plots.Plot{Plots.PlotlyBackend}) at /home/os/.julia/packages/Plots/GDtiZ/src/output.jl:150
 [16] display(::Any) at ./multimedia.jl:328
 [17] #invokelatest#1 at ./essentials.jl:710 [inlined]
 [18] invokelatest at ./essentials.jl:709 [inlined]
 [19] print_response(::IO, ::Any, ::Bool, ::Bool, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:238
 [20] print_response(::REPL.AbstractREPL, ::Any, ::Bool, ::Bool) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:223
 [21] (::REPL.var"#do_respond#54"{Bool,Bool,REPL.var"#64#73"{REPL.LineEditREPL,REPL.REPLHistoryProvider},REPL.LineEditREPL,REPL.LineEdit.Prompt})(::Any, ::Any, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:822
 [22] #invokelatest#1 at ./essentials.jl:710 [inlined]
 [23] invokelatest at ./essentials.jl:709 [inlined]
 [24] run_interface(::REPL.Terminals.TextTerminal, ::REPL.LineEdit.ModalInterface, ::REPL.LineEdit.MIState) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/LineEdit.jl:2355
 [25] run_frontend(::REPL.LineEditREPL, ::REPL.REPLBackendRef) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:1144
 [26] (::REPL.var"#38#42"{REPL.LineEditREPL,REPL.REPLBackendRef})() at ./task.jl:356

:frowning:

1 Like

The Plotly issue is because you are incorrectly supplying the vector of annotations - if you replace the comma with a semicolon you get something similar to the InspectDR output.

I haven’t been able to figure out a way of specifying the series_annotations in a way that don’t lead to strings being placed on all edges of the bars, which seems buggy to me. Unfortunately, groupedbar also doesn’t have a docstring so it’s hard to be sure about how this should work. I’d file an issue!

I’m guessing that removing the comma in the series_annotation didn’t work.

If you need an alternative, try Makie.jl

https://makie.juliaplots.org/dev/examples/plotting_functions/barplot/index.html

https://makie.juliaplots.org/dev/examples/plotting_functions/errorbars/index.html