Can someone explain to me how to theme a Makie boxplot such that I can colour boxes by specific conditions or ‘groups’, and also control the colour palette for this via a custom theme?
I can alter colour palette via the theme, and have boxplot colours reflect this:
using CairoMakie
CairoMakie.activate!(type = "pdf")
my_theme = Theme(
palette = (patchcolor = [:red, :green, :blue, :yellow, :orange, :pink],),
)
set_theme!(my_theme)
fig = Figure(backgroundcolor=:grey90)
axs = Axis(fig[1, 1], aspect=AxisAspect(1))
x = Vector{Float64}(undef, 40)
for i = 1:40
x[i] = i % 4
end
CairoMakie.boxplot!(axs, x, rand(40))
ylims!(axs, 0, 1)
save("figures/testcairo.pdf", fig)
(Plot is all red, indicating it’s responding to my change in colours - the default colour scheme would plot this as blue)
However if I now try to colour the box plots by a condition (for instance, if the x-variable is even or not), the palette reverts to the default Makie colour scheme:
Once you pass a vector of numbers as a color, these are looked up in the colormap by scaling with colorrange. To use a categorical colormap that way, set colormap = my_colors, colorrange = (1, length(my_colors))
This solution uses the first and last elements in my_colors for plotting. What’s the simplest means of having it use the order of elements in my_colors? i.e. for two conditions, use elements 1:2, for three conditions, use elements 1:3, and so on.
Ah hm you use 0 and 1 for colors, my solution was based on the groups being numbered 1 to k and the colorrange going from 1 to n colors. That should perfectly map to categorical colors, not interpolated ones, as long as k is not larger than n. Can you pass colormap and colorrange directly to the boxplot? I don’t think a colorrange belongs in a theme usually, as it’s too data dependent (unless we force categorical color lookup with it like here)
You still create color values 0 and 1 (false and true). Either the colorrange needs to then start at 0 or, what I find more straightforward, you start your color categories at 1. Here I’ve extrapolated the approach to multiple groups. mod1 is a handy function for starting the count at 1
fig = Figure(backgroundcolor=:grey90)
n = 200
x = Vector{Float64}(undef, n)
for i = 1:n
x[i] = mod1(i, 8)
end
colormap = Makie.to_colormap(:tab10)
for (i, k) in enumerate([2, 4, 6, 8])
ax = Axis(fig[fldmod1(i, 2)...])
CairoMakie.boxplot!(ax, x, rand(n);
color=map(x -> mod1(x, k), x), colormap,
colorrange = (1, length(colormap)))
ylims!(ax, 0, 1)
end
fig