plotjuliaplots.jl

How to give multiple plots a shared title in Plots.jl


I'm trying to plot several related plots in a grid and I'd like to give a shared title. However, when I use plot(plot1, plot2, title="my title") Plots.jl titles each separate plot with that title. Is there a way to fix this?

I tested the code below with the gr() and plotly() backend. Both have the same behavior.

    using Plots
    using DataFrames

    gr()  # plotly() backend has the same behavior
    
    anscombes_quartet = DataFrame([
    10.0    8.04    10.0    9.14    10.0    7.46    8.0     6.58
    8.0     6.95    8.0     8.14    8.0     6.77    8.0     5.76
    13.0    7.58    13.0    8.74    13.0    12.74   8.0     7.71
    9.0     8.81    9.0     8.77    9.0     7.11    8.0     8.84
    11.0    8.33    11.0    9.26    11.0    7.81    8.0     8.47
    14.0    9.96    14.0    8.10    14.0    8.84    8.0     7.04
    6.0     7.24    6.0     6.13    6.0     6.08    8.0     5.25
    4.0     4.26    4.0     3.10    4.0     5.39    19.0    12.50
    12.0    10.84   12.0    9.13    12.0    8.15    8.0     5.56
    7.0     4.82    7.0     7.26    7.0     6.42    8.0     7.91
    5.0     5.68    5.0     4.74    5.0     5.73    8.0     |6.89 
    ])
    
    rename!(anscombes_quartet, ["x1", "y1", "x2", "y2", "x3", "y3", "x4", "y4"])
    
    plot(
        scatter(anscombes_quartet.x1, anscombes_quartet.y1, label=""),
        scatter(anscombes_quartet.x2, anscombes_quartet.y2, label=""),
        scatter(anscombes_quartet.x3, anscombes_quartet.y3, label=""),
        scatter(anscombes_quartet.x4, anscombes_quartet.y4, label=""),
        title = "Anscombes quartet"
    )

enter image description here


Solution

  • I found a hacky solution, that uses an empty plot:

        using Plots: grid
        
        # make "title plot" really shallow
        l = @layout [
        a{0.001h}; grid(2,2)
        ]
        
        plot(
            plot(title="test", grid=false, showaxis = false, ticks = false),
            scatter(anscombes_quartet.x1, anscombes_quartet.y1, label=""),
            scatter(anscombes_quartet.x2, anscombes_quartet.y2, label=""),
            scatter(anscombes_quartet.x3, anscombes_quartet.y3, label=""),
            scatter(anscombes_quartet.x4, anscombes_quartet.y4, label=""),
            title = ["Anscombes quartet" "A"  "B"  "C"  "D"],
            titlelocation   = :left,
            titlefonthalign = :left,  # fixes plotly() text alignment
            layout = l
        )
    

    enter image description here

    One downside of this solution is that it doesn't allow you to adjust the "main title" separately since it's just another subtitle. For more info on the grid structure see the docs.

    If somebody knows a better solution, please let me know and I'll gladly accept it instead of my own.