How to assign colors to bar plots in StatsPlots / Plots

Hi all,

How do I assign colors to individual bars with StatsPlots. The following used to work with color. However something changed with Plots and now it does not work.

using DataFrames, StatsPlots
df = DataFrame(a = ["a","b"], b = [1,2])
@df df bar(:a, :b, colorfill=[:red, :blue])

The following works with color and row vectors, but this is not compatible with DataFrames

using DataFrames, StatsPlots
df = DataFrame(a = ["a","b"], b = [1,2])
bar(["a"  "b"], [1  2], color=[:red :blue])

Version:
Plots v1.12.0
StatsPlots v0.14.19

Try

df = DataFrame(a = ["a","b"], b = [1,2], c = [:red, :blue])
@df df bar(:a, :b, color=:c)

Thank you for your response. Unfortunately, that does not fix the problem. I receive the following error message:

 Warning: Indices Base.OneTo(2) of attribute `markercolor` does not match data indices 1:11.
└ @ Plots ~/.julia/packages/Plots/kyYZF/src/utils.jl:102
┌ Info: Data contains NaNs or missing values, and indices of `markercolor` vector do not match data indices.
│ If you intend elements of `markercolor` to apply to individual NaN-separated segements in the data,
│ pass each segment in a separate vector instead, and use a row vector for `markercolor`. Legend entries 
│ may be suppressed by passing an empty label.
│ For example,
└     plot([1:2,1:3], [[4,5],[3,4,5]], label=["y" ""], markercolor=[1 2])

Replacing color with fillcolor does not help either.

I opened an issue since it appears to be a bug.

I got the same error once I updated Plots to version 1.12.0.

The problem persists (also for Dictionaries). A workaround for DataFrames is:

@df df bar([[i] for i in :a], [[i] for i in :b], c=[:red :blue])

Notice the row vector for colors.
A graphical problem is that gaps between bars are greater than usual bar plots.

For Dictionaries the workaround is similar:

data= Dict("Item 1" => 30,
           "Item 2" => 35,
           "Item 3" => 25)
bar([[i] for i in keys(data)], [[i] for i in values(data)], legend=false, c=[:red3 :salmon :skyblue])

but it used to be much simpler:

bar(data, legend=false, c=[:red3, :salmon, :skyblue])
1 Like

Thank you for the solution.

I agree that it used to be much simpler. One of the problems is that it is now cumbersome for users to correctly assign the colors. I can imagine how this may lead to incorrect color assignment with datasets that have more factors and levels.