JuliaPlots / PlotlyJS.jl

Julia library for plotting with plotly.js

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Boxplot boxmode "group" doesn't work for subplots

dhanak opened this issue · comments

Describe the bug

Assume we have a series of boxplots:

julia> boxplots = [box(x=repeat(1:5,10), y=vec(randn(5, 10))) for _ in 1:3]

If I put these traces inside a plot, with boxmode set to "group", it works as expected:

julia> plot(boxplots, Layout(boxmode="group"))

boxmode working

But if I put the plot inside a subplot grid, the boxmode parameter is “forgotten”:

julia> vcat(plot(boxplots, Layout(boxmode="group")))

boxmode broken

It is similarly broken, obviously, when I put multiple subplots in the grid.

Version info

julia> versioninfo()
Julia Version 1.7.3
Commit 742b9abb4d (2022-05-06 12:58 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-12.0.1 (ORCJIT, skylake)
Environment:
  JULIA_PKG_USE_CLI_GIT = true

julia> using Pkg; pkg"status"
      Status `~/.julia/environments/v1.7/Project.toml`
  [6e4b80f9] BenchmarkTools v1.3.1
  [ad839575] Blink v0.12.5
  [a2441757] Coverage v1.6.0
  [31a5f54b] Debugger v0.7.6
  [54eb57ff] InteractiveCodeSearch v0.4.2
  [01369628] MyUtils v0.4.1 `~/CI/MyUtils.jl`
  [5fb14364] OhMyREPL v0.5.12
  [9b87118b] PackageCompiler v2.0.9
  [f0f68f2c] PlotlyJS v0.18.8
  [c46f51b8] ProfileView v1.5.1
  [e0db7c4e] ReTest v0.3.2
  [295af30f] Revise v3.4.0
fig = plot(boxplots, Layout(boxmode="group"))
typeof(fig)
PlotlyJS.SyncPlot

Hence you tried to vcat a single object, and PlotlyJS got confused.

I guess that you want a subplot with 3 rows and one column, to represent in each subplot cell the boxplots having the same color in the initial fig.
If this is a case this the solution:

p1= plot(boxplots[1])   
p2= plot(boxplots[2]) 
p3= plot(boxplots[3]) 
p =vcat(p1, p2, p3)
display(p)

Here p is also a PlotlyJS.SyncPlot.
I tried to define p =[plot(boxplots[i]) for i in 1:3], but in this case p is a Vector{PlotlyJS.SyncPlot} and cannot be displayed.
I'm familiar with the new way of creating subplots, via make_subplots.
A few tutorials for your PlotlyJS version can be found here https://plotly.com/julia/.

PlotlyJS got confused

No, there is no confusion. It is perfectly valid to create a 1×1 subplot grid, it should work just fine. But just to show that the issue is independent from this, here is a plot with multiple subplots:

julia> boxplots1 = [box(x=repeat(1:5,10), y=vec(randn(5, 10))) for _ in 1:3];
julia> boxplots2 = [box(x=repeat(1:5,10), y=vec(randn(5, 10))) for _ in 1:3];
julia> [plot(boxplots1, Layout(boxmode="group")); plot(boxplots2, Layout(boxmode="group"))]

box_3

You are using old style PlotlyJS, used with v<0.18. As I saw you have 0.18.8.

Here is the code for v>=0.18:

boxplots1 = [box(x=repeat(1:5,10), y=vec(randn(5, 10))) for _ in 1:3]
pl1=Plot(boxplots1, Layout(boxmode="group"))
boxplots2=[box(x=repeat(["A", "B","C"], 20), y=vec(randn(3, 20))) for j =1:2]
pl2=Plot(boxplots2, Layout(boxmode="group"))
fig = make_subplots(rows=2, cols=1,
specs=reshape([Spec(kind="box")
               Spec(kind="box")], 2,1))
for k=1:3
    add_trace!(fig, pl1.data[k], row=1, col=1)
end 
for k=1:2
    add_trace!(fig, pl2.data[k], row=2, col=1)
end 
relayout!(fig, height= 600, boxmode="group")
display(fig)

sbplts-box

Ah, I was using this page for documentation: https://juliaplots.org/PlotlyJS.jl/stable/ Which is, by the way, linked from the GitHub readme as well. I haven't realized that this page was stopped getting updates after version 0.14. One would assume that it would help to point to the up-to-date version of the documentation from all related pages.

I will check the new method of constructing subplots, but after a brief glance, it seems way more complicated than the old method. Thanks for pointing me in the right direction, anyway.

It's not so complicated, but I hastily copied and pasted here everything I had previously experimented,
to show how the subplots are generated.
This is the short way:

boxplots1 = [box(x=repeat(1:5,10), y=vec(randn(5, 10))) for _ in 1:3]
boxplots2 = [box(x=repeat(["A", "B","C"], 20), y=vec(randn(3, 20))) for j =1:2]
fig = make_subplots(rows=2, cols=1)
for k=1:3
    add_trace!(fig, boxplots1[k], row=1, col=1)
end 
for k=1:2
    add_trace!(fig, boxplots2[k], row=2, col=1)
end 
relayout!(fig, height= 600, boxmode="group")
display(fig)