Gadfly: Color Coding a Simple Bar Chart

suppose i’m working in a Jupyter notebook with a Julia kernel, and i want to plot some very simple data in a bar chart, to show the proportion of two quantities A and B, like so:

# Julia 1.6.1
using Gadfly

p = plot(x=["A", "B"], y=[81.7, 13.0], Geom.bar(position=:dodge))

img = SVG("foo.svg", 14cm, 8cm)
draw(img, p)

this gives me a bar chart, but i would also like to make the bars different colors (let’s say “yellow” and “blue”), to associate them to a different chart. i thought maybe i could do so by adding a Scale, like this:

p = plot(x=["A", "B"], y=[81.7, 13.0], Geom.bar(position=:dodge),
    Scale.color_discrete_manual("yellow", "blue"; order=[1, 2]))

img = SVG("foo.svg", 14cm, 8cm)
draw(img, p)

but i get this unexpected error when i try to display the plot:

MethodError: no method matching iterate(::Nothing)
Closest candidates are:
  iterate(::Union{LinRange, StepRangeLen}) at range.jl:664
  iterate(::Union{LinRange, StepRangeLen}, ::Int64) at range.jl:664
  iterate(::T) where T<:Union{Base.KeySet{var"#s79", var"#s78"} where {var"#s79", var"#s78"<:Dict}, Base.ValueIterator{var"#s77"} where var"#s77"<:Dict} at dict.jl:693
  ...

Stacktrace:
  [1] isempty(itr::Nothing)
    @ Base ./essentials.jl:767
  [2] render(guide::Gadfly.Guide.ColorKey, theme::Theme, aes::Gadfly.Aesthetics)
    @ Gadfly.Guide ~/.julia/packages/Gadfly/zv8pp/src/guide.jl:399
  [3] render(guide::Gadfly.Guide.ColorKey, theme::Theme, aes::Gadfly.Aesthetics, dynamic::Bool)
    @ Gadfly.Guide ~/.julia/packages/Gadfly/zv8pp/src/guide.jl:143
  [4] render_prepared(plot::Plot, coord::Gadfly.Coord.Cartesian, plot_aes::Gadfly.Aesthetics, layer_aess::Vector{Gadfly.Aesthetics}, layer_stats::Vector{Vector{Gadfly.StatisticElement}}, layer_subplot_aess::Vector{Vector{Gadfly.Aesthetics}}, layer_subplot_datas::Vector{Vector{Gadfly.Data}}, scales::Dict{Symbol, Gadfly.ScaleElement}, guides::Vector{Gadfly.GuideElement}; table_only::Bool, dynamic::Bool)
    @ Gadfly ~/.julia/packages/Gadfly/zv8pp/src/Gadfly.jl:813
  [5] render_prepared(plot::Plot, coord::Gadfly.Coord.Cartesian, plot_aes::Gadfly.Aesthetics, layer_aess::Vector{Gadfly.Aesthetics}, layer_stats::Vector{Vector{Gadfly.StatisticElement}}, layer_subplot_aess::Vector{Vector{Gadfly.Aesthetics}}, layer_subplot_datas::Vector{Vector{Gadfly.Data}}, scales::Dict{Symbol, Gadfly.ScaleElement}, guides::Vector{Gadfly.GuideElement})
    @ Gadfly ~/.julia/packages/Gadfly/zv8pp/src/Gadfly.jl:794
  [6] render(plot::Plot)
    @ Gadfly ~/.julia/packages/Gadfly/zv8pp/src/Gadfly.jl:740
  [7] draw(backend::SVG, p::Plot)
    @ Gadfly ~/.julia/packages/Gadfly/zv8pp/src/Gadfly.jl:843
  [8] top-level scope
    @ In[34]:5
  [9] eval
    @ ./boot.jl:360 [inlined]
 [10] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
    @ Base ./loading.jl:1094

i could not find an analogous usage in the Gadfly gallery, and i admit that i don’t see the problem in the usage of Scale.color_discrete_manual – or why it should make the plot fail when i add it.

is there some other way i can specify a manual color encoding for the bar chart?

You do need to map data to an aesthetic, before using a scale for that aesthetic. See the Gadfly Tutorial (perhaps we could add “Steps to build a plot”).

x = ["A", "B"]
p = plot(x=x, y=[81.7, 13.0], Geom.bar(position=:dodge),
        color=x,
    Scale.color_discrete_manual("yellow3", "steelblue")
)

thanks! this is exactly what i was looking for

and for what it’s worth, it looks like i did miss that important section of the tutorial; on re-reading it, i think this makes a lot more sense