Some code that does that
using CairoMakie, Random
# data
begin
n = 10
k = 3
rng = Random.MersenneTwister(0);
ys = [rand(rng, n) for _ in 1:k]
xs = [1:n for _ in 1:k]
end;
# transform data
begin
ys_flat = reduce(vcat, ys)
xs_flat = reduce(vcat, xs)
groups = reduce(vcat, [fill(i, length(x)) for (i,x) in enumerate(xs)])
end;
# plot data
begin
colors = Makie.wong_colors()
patterns = let
patternsymbols = ["/", "x", "-"]
[Pattern(pat, background_color=col, linecolor = :black) for (col,pat) in zip(colors, patternsymbols)]
end
offsets = let
ys_cumsum = accumulate(+, ys[1:end-1])
pushfirst!(ys_cumsum, zero(ys_cumsum[1]))
end
end;
# get Makie dodge x values
function compute_x(x, dodge; width=1, gap=0.2, dodge_gap=0.03)
scale_width(dodge_gap, n_dodge) = (1 - (n_dodge - 1) * dodge_gap) / n_dodge
function shift_dodge(i, dodge_width, dodge_gap)
(dodge_width - 1) / 2 + (i - 1) * (dodge_width + dodge_gap)
end
width *= 1 - gap
n_dodge = maximum(dodge)
dodge_width = scale_width(dodge_gap, n_dodge)
shifts = shift_dodge.(dodge, dodge_width, dodge_gap)
return x .+ width .* shifts
end
# Normal dodge barplot
let
barplot(xs_flat, ys_flat; dodge=groups, color=colors[groups])
end
# Dodge barplot with patterns
let
fig = Figure()
a = Axis(fig[1,1])
uniquegroups = unique(groups)
dodge_gap = 0.03 #Makie default
gap = 0.2 #Makie default
width = 1 #Makie default
widthplot = width / (length(uniquegroups) + 0.2) # work around
xs_explicit_flat = compute_x(xs_flat, groups; width, gap, dodge_gap)
for (g,pat) in zip(uniquegroups, patterns)
indices = findall(==(g), groups)
ys_g = ys_flat[indices]
xs_g = xs_explicit_flat[indices]
barplot!(a, xs_g, ys_g; color=pat, dodge_gap, gap, width=widthplot)
end
fig
end
# Stacked barplot with pattern
let
fig = Figure()
a = Axis(fig[1,1])
uniquegroups = unique(groups)
dodge_gap = 0.03 #Makie default
gap = 0.2 #Makie default
width = 1 #Makie default
widthplot = width / (length(uniquegroups) + 0.2) # work around
for (g,pat,offs) in zip(uniquegroups, patterns, offsets)
indices = findall(==(g), groups)
ys_g = ys_flat[indices]
xs_g = xs_flat[indices]
barplot!(a, xs_g, ys_g; color=pat, offset=offs, gap, width=widthplot)
end
fig
end