Plots: Using multiple colours in title

Thanks for all of your suggestions! All good options. In the end, I decided to use annotate. Indeed, it is a major hack and not the prettiest, but it works well for my purposes (I have 9 sets of 6 x 6 grids with no space left for a legend, and I only need to use the title to identify which colour corresponds to each group.)

In case someone needs to do something similar in the future, here is the code that I used (note that I used this stack overflow answer as a starting point):


"""
	coloured_title(
	p, group_names, colours;
	horizontal_shift = -0.25, vertical_shift = 0,
	size = 18, title_spacing_constant = 4, title_proportion = 0.02
	)

Adds a rudimentary coloured title to `p`. The title is constructed by colouring
each element of `group_names` with the corresponding element of `colours`, and
joining the results. The remaining arguments allow the title to be 'tweaked' as
needed.
"""
function coloured_title(
	p, group_names::Vector{String}, colours::Vector{String};
	horizontal_shift = -0.25, vertical_shift = 0,
	size = 18, title_spacing_constant = 4, title_proportion = 0.02
	)

	@assert length(group_names) == length(colours)
	@assert -1 < horizontal_shift < 1
	@assert -1 < vertical_shift < 1
	@assert 0 < title_proportion < 1
	@assert title_spacing_constant >= 0

    # Empty plot that will be used for the title
    y = ones(3)
    title_plot = scatter(
        y,
        xlims = (-1, 1),
        ylims = (-1, 1),
        marker=0, markeralpha=0,axis=false, grid=false, leg=false,
        framestyle = nothing, showaxis = false, xticks = false, yticks = false
    )

    # Add coloured text in the middle of the plot; each subsequent group name
    # is shifted by an amount that is proportional to maximum(length.(group_names))
    for i ∈ eachindex(group_names)
        max_len = maximum(length.(group_names))
        current_title = repeat(" ", title_spacing_constant * max_len * (i - 1)) * group_names[i]
        annotate!(title_plot, horizontal_shift, vertical_shift, Plots.text(current_title, colours[i], size))
    end

	# layout for the title plot and your real plot
	l = grid(2, 1, heights = [title_proportion, 1 - title_proportion])

    # combine the 'title' plot with your real plots
    return plot(title_plot, p, layout = l)
end

And here is an example of its use:

# Generate toy data
n = 20 # number of observations per group
x = repeat(1:n, outer = 2)
y = repeat([0, 10], inner = n) .+ randn(2n)
group_names = ["Group 1", "Group 2"]
colours = ["green", "orange"]
c = repeat(colours, inner = n)

# real plot
p = plot(x, y, group = c, colour = c, legend = :none)

coloured_title(p, group_names, colours)

toy

1 Like