Skip to content

Commit a3550e6

Browse files
Merge pull request #2866 from plotly/fig-set-subplots
`go.Figure.set_subplots`
2 parents d154171 + 1816695 commit a3550e6

File tree

6 files changed

+87
-5
lines changed

6 files changed

+87
-5
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
44

55
## [4.13.0] - UNRELEASED
66

7+
### Added
8+
9+
- `go.Figure` now has a `set_subplots` method to set subplots on an already
10+
existing figure.
711

812

913
## [4.12.1] - UNRELEASED

doc/python/subplots.md

+20
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,26 @@ fig = go.Figure(data=data, layout=layout)
581581
fig.show()
582582
```
583583

584+
#### Setting Subplots on a Figure Directly
585+
586+
_new in 4.13_
587+
588+
Subplots can be added to an already existing figure, provided it doesn't already
589+
have subplots. `go.Figure.set_subplots` accepts all the same arguments as
590+
`plotly.subplots.make_subplots`.
591+
592+
```python
593+
import plotly.graph_objects as go
594+
fig = go.Figure().set_subplots(2, 3, horizontal_spacing=0.1)
595+
```
596+
597+
is equivalent to:
598+
599+
```python
600+
from plotly.subplots import make_subplots
601+
fig = make_subplots(2, 3, horizontal_spacing=0.1)
602+
```
603+
584604
#### Reference
585605
All of the x-axis properties are found here: https://plotly.com/python/reference/XAxis/
586606
All of the y-axis properties are found here: https://plotly.com/python/reference/YAxis/

packages/python/plotly/plotly/basedatatypes.py

+17
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from .optional_imports import get_module
1515

1616
from . import shapeannotation
17+
from . import subplots
1718

1819
# Create Undefined sentinel value
1920
# - Setting a property to None removes any existing value
@@ -3935,6 +3936,22 @@ def _subplot_not_empty(self, xref, yref, selector="all"):
39353936
)
39363937
return ret
39373938

3939+
def set_subplots(self, rows=None, cols=None, **make_subplots_args):
3940+
"""
3941+
Add subplots to this figure. If the figure already contains subplots,
3942+
then this throws an error. Accepts any keyword arguments that
3943+
plotly.subplots.make_subplots accepts.
3944+
"""
3945+
# rows, cols provided so that this can be called like
3946+
# fig.set_subplots(2,3), say
3947+
if rows is not None:
3948+
make_subplots_args["rows"] = rows
3949+
if cols is not None:
3950+
make_subplots_args["cols"] = cols
3951+
if self._has_subplots():
3952+
raise ValueError("This figure already has subplots.")
3953+
return subplots.make_subplots(figure=self, **make_subplots_args)
3954+
39383955

39393956
class BasePlotlyType(object):
39403957
"""

packages/python/plotly/plotly/subplots.py

+16-5
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def make_subplots(
6060
row_titles=None,
6161
x_title=None,
6262
y_title=None,
63+
figure=None,
6364
**kwargs
6465
):
6566
"""
@@ -226,7 +227,15 @@ def make_subplots(
226227
227228
y_title: str or None (default None)
228229
Title to place to the left of the left column of subplots,
229-
centered vertically
230+
centered vertically
231+
232+
figure: go.Figure or None (default None)
233+
If None, a new go.Figure instance will be created and its axes will be
234+
populated with those corresponding to the requested subplot geometry and
235+
this new figure will be returned.
236+
If a go.Figure instance, the axes will be added to the
237+
layout of this figure and this figure will be returned. If the figure
238+
already contains axes, they will be overwritten.
230239
231240
Examples
232241
--------
@@ -809,13 +818,15 @@ def _checks(item, defaults):
809818
print(grid_str)
810819

811820
# Build resulting figure
812-
fig = go.Figure(layout=layout)
821+
if figure is None:
822+
figure = go.Figure()
823+
figure.update_layout(layout)
813824

814825
# Attach subplot grid info to the figure
815-
fig.__dict__["_grid_ref"] = grid_ref
816-
fig.__dict__["_grid_str"] = grid_str
826+
figure.__dict__["_grid_ref"] = grid_ref
827+
figure.__dict__["_grid_str"] = grid_str
817828

818-
return fig
829+
return figure
819830

820831

821832
def _configure_shared_axes(layout, grid_ref, specs, x_or_y, shared, row_dir):

packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_figure.py

+20
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
from __future__ import absolute_import
22

33
import plotly.graph_objects as go
4+
from plotly.subplots import make_subplots
45
from plotly.tests.utils import TestCaseNoTemplate
6+
import pytest
57

68

79
class FigureTest(TestCaseNoTemplate):
@@ -199,3 +201,21 @@ def test_update_overwrite_data(self):
199201
fig.to_plotly_json()["data"],
200202
[{"type": "scatter", "y": [1, 3, 2], "line": {"color": "yellow"}}],
201203
)
204+
205+
206+
def test_set_subplots():
207+
# Test that it works the same as make_subplots for a simple call
208+
fig0 = go.Figure()
209+
fig0_sp = make_subplots(2, 2)
210+
fig0.set_subplots(2, 2)
211+
assert fig0.layout == fig0_sp.layout
212+
# Test that it accepts the same arguments as make_subplots
213+
fig1 = go.Figure()
214+
fig1.set_subplots(rows=2, cols=2, horizontal_spacing=0.25, vertical_spacing=0.1)
215+
fig1_sp = make_subplots(
216+
rows=2, cols=2, horizontal_spacing=0.25, vertical_spacing=0.1
217+
)
218+
assert fig1.layout == fig1_sp.layout
219+
# Test that calling on a figure that already has subplots throws an error.
220+
with pytest.raises(ValueError, match=r"^This figure already has subplots\.$"):
221+
fig1.set_subplots(2, 3)

packages/python/plotly/plotly/tests/test_core/test_subplots/test_make_subplots.py

+10
Original file line numberDiff line numberDiff line change
@@ -1924,3 +1924,13 @@ def test_secondary_y_subplots(self):
19241924
expected.update_traces(uid=None)
19251925

19261926
self.assertEqual(fig.to_plotly_json(), expected.to_plotly_json())
1927+
1928+
def test_if_passed_figure(self):
1929+
# assert it returns the same figure it was passed
1930+
fig = Figure()
1931+
figsp = subplots.make_subplots(2, 2, figure=fig)
1932+
assert id(fig) == id(figsp)
1933+
# assert the layout is the same when it returns its own figure
1934+
fig2sp = subplots.make_subplots(2, 2)
1935+
assert id(fig2sp) != id(figsp)
1936+
assert fig2sp.layout == figsp.layout

0 commit comments

Comments
 (0)