Is it possible to plot a figure containing axis break like this using Plots.jl and GR backend?
Especially in boxplot.
Is it possible to plot a figure containing axis break like this using Plots.jl and GR backend?
Especially in boxplot.
Never saw such type of example done with gr()
, but you may try to implement it using the same subplot trick as done here by @ianshmean
Using the subplot trick mentioned above, the following plots with breaks can be obtained using gr()
back-end, but the code is a bit shaky:
Using gr’s ggplot2 theme with no breaks:
Using gr’s ggplot2 theme with breaks:
xb = [(500,800), (1900,2100)]
yb = [(100,300), (500,650), (850,900)]
Using gr’s dark theme with breaks:
Using gr’s dark theme with breaks, but in log-log scale:
Using gr’s ggplot2 theme with 1 ybreak:
xb = [] # empty set for no breaks
yb = [(100,300)]
Here below the code, with a user function breakplot()
defined:
using Measures, Plots; gr()
function breakplot(X,Y,xb,yb; lc=:yellow,lw=3,ls=:solid,xlabel="X-axis",ylabel="Y-axis",ptheme=:dark,
xscale=:identity, yscale=:identity, size = (1000,700))
# by @rafael.guerra
if occursin("dark",lowercase(string(ptheme)))
gc =:white
else
gc =:black
end
nx, ny = length(xb), length(yb)
xb2 = [X[1]; collect(Iterators.flatten(xb)); X[end]]
yb2 = [minimum(Y); collect(Iterators.flatten(yb)); maximum(Y)]
w = [diff(xb2[2(i-1)+1:2*i])[1] for i in 1:nx+1]
if occursin("log10",lowercase(string(xscale)))
w = log10.(w)
end
w = w / sum(w)
h = [diff(yb2[2(i-1)+1:2*i])[1] for i in 1:ny+1]
if occursin("log10",lowercase(string(yscale)))
h = log10.(h)
end
h = reverse(h) / sum(h)
theme(ptheme)
l = @layout [a{0.001w} [grid(ny+1,nx+1, heights=h, widths=w); b{0.001h}]] # first & last subplots for axes labels
p = fill(plot( lw=lw,ls=ls), 1 + (ny+1) * (nx+1) + 1)
p[1] = plot(ylabel=ylabel, guidefont=font(10,gc),guide_position=:right,showaxis=false,xticks=false,yticks=false,margin=5mm)
for j in 1:ny+1
jj = (ny+1) - j + 1
ylj = yb2[2(j-1)+1:2*j]
for i in 1:nx+1
xli = xb2[2(i-1)+1:2*i]
ix = (jj-1)*(nx+1) + i
if (i == 1) & (j != 1)
p[1+ix] = plot(X,Y, xlims=xli, ylims=ylj,framestyle=:default,legend=false,margin=0mm,lc=lc,tickfontsize=6,
xshowaxis=false,xticks=false,xscale=xscale,yscale=yscale, size=(size[1]*h[j],size[2]*w[i]))
elseif (i != 1) & (j == 1)
showaxis=:x
p[1+ix] = plot(X,Y, xlims=xli, ylims=ylj,framestyle=:default,legend=false,margin=0mm,lc=lc,tickfontsize=6,
yshowaxis=false,yticks=false,xscale=xscale,yscale=yscale, size=(size[1]*h[j],size[2]*w[i]))
elseif (i == 1) & (j == 1)
p[1+ix] = plot(X,Y, xlims=xli, ylims=ylj,framestyle=:default,legend=false,margin=0mm,lc=lc,tickfontsize=6,
xscale=xscale,yscale=yscale, size=(size[1]*h[j],size[2]*w[i]))
else
p[1+ix] = plot(X,Y, xlims=xli, ylims=ylj,framestyle=nothing,legend=false,margin=0mm,lc=lc,showaxis=false,
xticks=false,yticks=false,xscale=xscale,yscale=yscale, size=(size[1]*h[j],size[2]*w[i]))
end
end
end
p[end] = plot(xlabel=xlabel, guidefont=font(10,gc),guide_position=:top,showaxis=false,xticks=false,yticks=false,margin=5mm)
plot(p..., layout=l, grid=false, size=size)
end
# Examples:
X = 1:2500.0
Y = 1000*(sin.(X/500)).^2 .+ 1
xb = [(500,800), (1900,2100)]
yb = [(100,300), (500,650), (850,900)]
theme(:default)
plot(X,Y, xlabel="Time [min]",ylabel="Trajectory altitude [m]", legend=false)
breakplot(X,Y,xb,yb; lc=:blue, xlabel="Time [min]",ylabel="Trajectory altitude [m]",ptheme=:ggplot2)
breakplot(X,Y,xb,yb; lc=:yellow, xlabel="Time [min]",ylabel="Trajectory altitude [m]")
breakplot(X,Y,xb,yb; lc=:yellow, xlabel="Time [min]",ylabel="Trajectory altitude [m]", xscale=:log10,yscale=:log10)
xb = [] # empty set for no breaks
yb = [(100,300)]
breakplot(X,Y,xb,yb; lc=:blue, xlabel="Time [min]",ylabel="Trajectory altitude [m]",ptheme=:ggplot2)
It seems nice but I cannot found the example code.
Can you share an example or any link?
@iHany, as requested the user function code and examples were updated above.
As indicated, this subplot business in Plots.jl and gr()
is a bit shaky…
If you see things that can be obviously improved, please do share.
NB: there was a bug on the list of vertical proportions which were in reverse order. Fixed now.
Ok…
I think that your remedy works fine but it needs additional efforts as you said.
It seems that there are already some issues reported in Plots.jl such as this, so subplot method would be the best for now.
Thanks for sharing your example