I have to Julia datasets that share the same Y-axes. I want to plot these side by side using layout, but have the two plots abutting, with no white space between them, while preserving outer margins for the tick labels and axis label on the left-hand plot.
Ideally I'd like to have the plot regions align, and have tick marks on the right-hand plot pointing into the plot space of the left-hand plot (with no tick labels).
In R (which I'm more familiar with), I could achieve this by setting the internal margins to zero (e.g., par(mrow=c(1,2), mar=c(0,0,0,0), oma=c(4,4,1,1)).
Minimum example.
using Plots
x = 1:10
y1 = rand(10)
y2 = rand(10)
plot1 = plot(x, y1, label="Plot 1", ylabel="Shared Y-Axis", framestyle=:box, right_margin=0mm)
plot2 = plot(x, y2, label="Plot 2", yticks=[] , framestyle=:box, left_margin=0mm)
l = @layout [a b]
plot(plot1, plot2, layout=l, left_margin=0mm, right_margin=0mm)
display(Plots.plot!())
Thanks!
I tried setting margins to 0, both in the plot function and in the layout function. I also tried setting custom width and height in the layout macro.
I'm pretty sure you can't accomplish what you ideally want to do with the default GR back-end (maybe any of the possible Plots.jl backends?), but here are two possible answers for you (other may have better solutions!) that may work:
using PyPlot
fig = figure("pyplot_dual_axis",figsize=(10,5)) #figsize controls x,y size of figure
subplots_adjust(wspace=0.0) #remove horizontal space between subplots
subplot(121) #1 row, 2 columns 1st plot (left)
ax1= gca() #get the current axis
ax1.plot([1,2,3],[1,2,3]) #plot to it
subplot(122,sharey=ax1) #1 row, 2 columns 2nd plot (right)
ax2 = gca() #get the newly created axis for right plot
ax2.plot([1,2,3],[1,2,3]) #plot to it
fig.canvas.draw() #update the figure
suptitle("Dual y-axis example") #add a title
gcf() #get current figure, needed for some inline plotting in Julia(?)
This produces the following figure:
For further customization you can pretty much just google "matplotlib how do I do [x]" and even though you are coding in Julia the result will mostly still apply as you can call all the ax
and fig
methods you need to from Julia using PyPlot.jl.
function draw_custom_axis!(P,origin,orientation,ticks,tickLabels=nothing,tickLength=0.05)
P = orientation == "y" ? plot!(P,[origin,origin],[minimum(ticks),maximum(ticks)],c="black",label="") : plot!(P,[minimum(ticks),maximum(ticks)],[origin,origin],c="black",label="")
for (i,tick) in enumerate(ticks)
P = orientation == "y" ? plot!([origin,origin-tickLength],[tick,tick],c="black",label="") : plot!([tick,tick],[origin,origin-tickLength],c="black",label="")
if tickLabels != nothing
t = orientation == "y" ? Plots.text("$(tickLabels[i])",rotation=90,halign=:hcenter,valign=:bottom) : Plots.text("$(tickLabels[i])",halign=:hcenter,valign=:top)
P = orientation == "y" ? annotate!((origin-tickLength,tick,t)) : annotate!((tick,origin-tickLength,t))
end
end
return P
end
Creating an empty canvas as a plot and then calling this will produce a similar result to what you want as well:
P = plot(frame=false,axis=false,xlims=(-0.5,5.5),ylims=(-0.5,5.5)) #initialize empty white plot
P = draw_custom_axis!(P,0,"y",[0,1,2,3,4,5],["$i" for i=0:5],0.1) #add a y axis that goes up from x=0 with tick marks at 0,1,2,3,4,5 and associated labels, with tick width = 0.1
P = draw_custom_axis!(P,3,"y",[0,1,2,3,4,5],["","1","2","3","4","5"],0.1) #add a second y axis that goes up from x = 3, and this time omitting the first tick label for aesthetics
P = draw_custom_axis!(P,0,"x",[0,1,2,3,4,5],["","1","2","0","1","2"],0.1) #add the x axis, with 5 tick marks but set the labels to start over at x=3 since this is where we added the second y axis and where the second "plot" begins
P = plot!([rand()*2 for i=1:5],[rand()*5 for i=1:5],label="data 1") #plot some data in the left plot (which goes up to x=3)
P = plot!(3 .+[rand()*2 for i=1:5],[rand()*5 for i=1:5],label="data 2") #plot some data in the right half, which has a span of 2 and starts at x=3 but has the same height in y
This results in the following figure:
The advantages here are that you don't need to install a new package and you can use all the well Julia Plots documentation (which is pretty good!), and you get infinite customization options because you're making everything yourself, but the downside is that you have to make it yourself and do it in a little bit of a "hacky" way. For what it's worth I usually do something like this when I have some "niche" (not that this is actually that niche -- it really is something the library should just do by default) that I want to do. It usually ends up looking the best to you when you have full control over everything!