In Plots.jl, can I have a single x axis for a grid of plots?

I have an array of plots (49 of them so it’s a fairly large figure)

plts = Plots.Plot[]
for i = 1:49 
   p = plot(...)
   push!(plts, p)
end
plot(plts..., layout = 49, size=(2000, 2000), link=:x, margin=-1mm)

I have two questions here

  1. Each plot gets its own x axis and y axis. Since the x-axis is the same for all plots, I’d like a single axis at the bottom of each column. I thought the link = :x would work, but I don’t know if I am using it correctly.

  2. The y-tick-labels have a large gap between the y axis. (note, I am not talking about the axis label… but the actualy axis-tick values). Is there a way to reduce this margin?

1 Like

Maybe Plots.link_axes!()

Below outputs a set of 49 plots.

using Plots

C = [0.0005, 0.01, -0.003, 0.00029]
inS, outS = 52, 49
dampen = 0.95

X=zeros(Float64, inS)

# Create synthetic input set.
for i ∈ 1:inS
    X[i] = 0.125i
end

Y = zeros(Float64, (inS, outS))

# Create synthetic output set.
for k ∈ 1:length(Y[1,:])  # For each output Y[n].
    for j ∈ 1:length(X) # For each input X[n].
        Y[j, k]=(C[4]*(X[j]^3)+C[3]*(X[j]^2)+C[2]*X[j]+C[1]) * dampen
    end
    global dampen *= 0.95
end

plot(size=(1000, 1000))

for i ∈ 1:length(Y[1,:])
    display(plot!(X,Y[:,i]))
end


Actually, I meant something like this:

1 Like

If you want to move beyond Plots.jl, you can look at https://github.com/JuliaPlots/AlgebraOfGraphics.jl. It builds a layer on top of AbstractPlotting/Makie. It can do this.

Queryverse is a nice option.

using Queryverse
using RDatasets: dataset

dataset("ggplot2", "mpg") |>
    @vlplot(:point, x=:Displ, y=:Hwy, column="Class:n", row="Cyl:n")

Maybe this is enough, inside an appropriate loop, using Plots:

julia> x = rand(10) ; y = rand(10) ;

julia> plot(layout=(2,2),framestyle=:box)

julia> plot!(x,y,xformatter=_->"",subplot=1)

julia> plot!(x,y,xformatter=_->"",yformatter=_->"",subplot=2)

julia> plot!(x,y,subplot=3)

julia> plot!(x,y,yformatter=_->"",subplot=4)

julia> plot!(xlim=[0,1],ylim=[0,1])

image

Another option - using MakieLayout, see an example with common y-axis from here: MakieLayout.jl Tutorial · MakieLayout.jl

it works for me with link=:all.

1 Like

This is interesting: it works for me with link=:all . I am wondering, if :
Is it also possible to link two subplots like subplot 1 and 2 in a plot(layout(2,2))?

This may not be the elegant way, but it is possible.

x = range(0,1,101)
p1 = plot(x,[sin.(x) exp.(x)],layout=(2,1),link=:all,label=nothing);
p2 = plot(x,[cos.(x) tan.(1.5x)],layout=(2,1),label=nothing);
plot(p1,p2,layout=(1,2))

If organizing the 2x2 display by columns (as in @tobydriscoll’s nice example) one can link :all or :x, but not the :y axes

On the other hand, if organizing it by rows, one can link :all or :y, but not the :x axes

This seems to be consistent with the link keyword description in the Plots attributes section.

I have found a workaround, which works for me, but I think it is not elegant:

plot(layout=(2,2), link=:all)

Which links all axes. I have to zoom in subplot 3 and subplot 3 with the xlims, ylims option. I was hoping that one could doing something like this:

plot(layout=(2,2), link=<<only a subset of the subplots>>)

I guess that this feature does not exist (yet)