alexarchambault/plotly-scala

the limitation of the number of subplots

Closed this issue · 2 comments

Hi, I have a question about the limitation of subplots.
I don't know this is the right place to ask but I can't find the other place to ask my question.
So If this is not, I will remove this right away.

I have chosen this plotly-scala library for my data visualization.
My treated data has a large amount so I need to split plots into more than 4 plots in one direction.
But, although plotly-scala 0.8.2 was released with Grid object I found out there is a limitation of the number of subplots
because AxisReference is applied only for X, X1~X4 and four subplots are available in one direction.
I wonder this isn't able to be improved, if so, plotly.js can't support multi subplots more than 4 in one direction.
If there is a solution in this version I want to know how to write code for this.

I wish I would fork and improve code by myself but I am afraid I'm insufficient to modify code in programming skill.
Thanks.

First of all, it is possible to improve plotly-scala to support multi subplots more than 4 in the future, but I think there isn't straightforward way to workaround limitation of axis in the current version.

Plotly.js arranges subplots according to layout.width, layout.height, layout.xaxis<N>.domain and layout.yaxis<N>.domain parameters.

For example, if when you arrange 3x3 graphs in 600x600 layout, the json passed to plotly.js is something like below.

var layout = {
  width: 600,
  height: 600,
  // the first row, which occupies 1/3 of layout
  
  //  xaxis-yaxis is located in left-top of layout
  xaxis: {
    domain: [0, 0.33],
    anchor: 'y1'
  },
  yaxis: {
    domain: [0, 0.33],
    anchor: 'x1'
  },
  // xaxis2-yaxis2 is located in center-top of layout 
  xaxis2: {
    domain: [0.33, 0.66],
    anchor: 'y2'
  },
  yaxis2: {
    domain: [0,0.33],
    anchor: 'x2'
  },
  // xaxis3-yaxis3 is located in right-top of layout
  xaxis3: {
    domain: [0.66, 1],
    anchor: 'y3'
  },
  yaxis3: {
    domain: [0, 0.33],
    anchor: 'x3'
  },
   // the second row
   
   // xaxis4-yaxis4 is located in left-middle of layout
  xaxis4: {
    domain: [0, 0.33],
    anchor: 'y1'
  },
  yaxis4: {
    domain: [0.33, 0.66],
    anchor: 'x4'
  },
  xaxis5: {
    domain: [0.66, 1],
    anchor: 'y5'
  },
  yaxis5: {
    domain: [0.33,0.66],
    anchor: 'x5'
  },
  xaxis6: {
    domain: [0.66, 1],
    anchor: 'y6'
  },
  yaxis6: {
    domain: [0.33, 0.66],
    anchor: 'x6'
  },
  //  the third row
  //  ....
};

To understand it, you can try and edit plotly graphs here.
Click JSON -> tree in the left sidebar and you can inspect json schema for graphs.

Unfortunately, it seems that plotly-scala has yet to implement this feature.

I think there should be interfaces like make_subplots in plotly.py, which is a python wrapper for plotly.js, to caluculate domains of each axis from width, height, row and col values (or to directly specify row and col domains of each axis) and then generate json.

from plotly.subplots import make_subplots

fig = make_subplots(
    rows=2, cols=1,
    row_width=[0.33, 0.67],
    start_cell="top-left")

fig.add_scatter(y=[2, 1, 3], row=1, col=1)
fig.add_bar(y=[2, 3, 1], row=2, col=1)
fig.show()

In plotly-scala, Layout.scala has a limited number of axis fields(xaxis, xaxis1 to xaxis4, yaxis, yaxis1 to yaxis4) while plotly.js's layout object can have arbitrary number of xaxis and yaxis fields.

Layout.scala represents plotly.js's layout object and its corresponding json but it seems more difficult to enable Layout.scala to have arbitrary number of axis fields to directly encode json than to create a helper class or a function as the python library do.

@data(optionSetters = true) class Layout(
          // ....
          xaxis: Option[Axis] = None,
          yaxis: Option[Axis] = None,
         xaxis1: Option[Axis] = None,
         xaxis2: Option[Axis] = None,
         xaxis3: Option[Axis] = None,
         xaxis4: Option[Axis] = None,
         yaxis1: Option[Axis] = None,
         yaxis2: Option[Axis] = None,
         yaxis3: Option[Axis] = None,
         yaxis4: Option[Axis] = None,
        // ....
        barmode: Option[BarMode] = None,
       autosize: Option[Boolean] = None,

I will try to make PR to add a helper class to support subplots more than 4.

Thanks ItoYo16u. It's really helpful to understand.
I hope this will be implemented soon.
So I close this issue and I will take a look at #299.