I am plotting 20+ timeseries with various scales from a DataFrame
using Plots.jl
, separated into subplots because the original plot is too crowded. Everything works nicely, but I would like a separate legend (with only the plotted series) for each subplot. Self-contained toy example:
using DataFrames
using Plots
using StatPlots
data = let years=[], spelltypes=[], values=[]
for year in 1980:2000
for spelltype in 1:30
push!(values, spelltype+(rand()-0.5)/10)
push!(years, year)
push!(spelltypes, spelltype)
end
end
DataFrame(year=years, spelltype=spelltypes, value=values)
end
pick(data, range) = data[[spelltype â range for spelltype in data[:spelltype]],:]
subplot(data, range) = plot(pick(data, range), :year, :value, group=:spelltype)
p1 = subplot(data, 1:10)
p2 = subplot(data, 11:20)
p3 = subplot(data, 21:30)
plot(p1, p2, p3) # would like separate legend for each subplot
2 Likes
Funny, I get separate legends in each subplot when trying that code
Yeah separate legends is easy and automatic. Did you mean you didnât want separate legends and just wanted a master legend? Thatâs difficult and I think I have an issue open for that.
@mkborregaard, @ChrisRackauckas: now I have tried various backends. I get separate legends in gr()
, but a single legend in plotly()
and plotlyjs()
, and an error for pyplot()
:
julia> pyplot()
INFO: Recompiling stale cache file /home/tamas/.julia/lib/v0.5/PyPlot.ji for module
PyPlot.
Plots.PyPlotBackend()
julia> plot(p1, p2, p3) # would like separate legend for each subplot
Error showing value of type Plots.Plot{Plots.PyPlotBackend}:
ERROR: MethodError: no method matching py_init_subplot(::Plots.Plot{Plots.PyPlotBac
kend}, ::Plots.Subplot{Plots.PlotlyBackend})
Closest candidates are:
py_init_subplot(::Plots.Plot{Plots.PyPlotBackend}, ::Plots.Subplot{Plots.PyPlotBa
ckend}) at /home/tamas/.julia/v0.5/Plots/src/backends/pyplot.jl:393
Using released versions of all packages, and 0.5.0
.
Is the above not the syntax I should be using?
AFAICS there is nothing wrong with your syntax. It is strange. I am on Plots master and PyPlot release.
I tried master for Plots
, PlotlyJS
and Plotly
, and I get the combined legend. With master PyPlot
, I do get the separate legends.
I think the best course of action is to open an issue on Plots
Apologies for reopening an older post, but I have a panel of plots (using Plots.jl) and specifying legend=true at the end while specifying the layout makes it very messy and shows giant legends that cover up most of the subplots. Iâd like to specify a master legend i.e. one legend for all subplots, how would I do that?
Thank you!
You can always hack it together with layout
and an extra subplot.
plot(
plot(rand(100,3), legend = false),
plot((1:3)', legend = true, framestyle = :none)
)
2 Likes
So the issue here is that I have originally 15 subplots, and doing âlayout=(5,3)â fits the graphs well, however if I add the master legend bit as an extra subplot (I had tried doing this earlier myself), it shows an error saying âWhen doing layout, n(15) != n_override(16). Youâre probably trying to force existing plots into a layout that doesnât fit them.â Iâve tried playing around with the layout (i.e. Iâve tried tuples of (8,2) to fit the legend subplot but this layout highly distorts the graphs, or layout=(6,3) to accommodate for the extra graph), but it keeps showing the error message, which means that Plots.jl requires exactly the same correct number of subplots in total as specified in the layout. Is there a workaround?
You can use a 4x4 layout. Leave the 16th empty, then plot to it with plot!(...somearguments..., subplot = 16, framestyle = :none)
1 Like
this is perfect, thank you!