Skip to content

Commit 86f4217

Browse files
Merge branch 'master' into deep-magic-underscore-error-msg-rebase
2 parents 4066ae2 + a3550e6 commit 86f4217

File tree

6 files changed

+87
-5
lines changed

6 files changed

+87
-5
lines changed

Diff for: 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

Diff for: 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/

Diff for: packages/python/plotly/plotly/basedatatypes.py

+17
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from .optional_imports import get_module
2525

2626
from . import shapeannotation
27+
from . import subplots
2728

2829
# Create Undefined sentinel value
2930
# - Setting a property to None removes any existing value
@@ -4134,6 +4135,22 @@ def _subplot_not_empty(self, xref, yref, selector="all"):
41344135
)
41354136
return ret
41364137

4138+
def set_subplots(self, rows=None, cols=None, **make_subplots_args):
4139+
"""
4140+
Add subplots to this figure. If the figure already contains subplots,
4141+
then this throws an error. Accepts any keyword arguments that
4142+
plotly.subplots.make_subplots accepts.
4143+
"""
4144+
# rows, cols provided so that this can be called like
4145+
# fig.set_subplots(2,3), say
4146+
if rows is not None:
4147+
make_subplots_args["rows"] = rows
4148+
if cols is not None:
4149+
make_subplots_args["cols"] = cols
4150+
if self._has_subplots():
4151+
raise ValueError("This figure already has subplots.")
4152+
return subplots.make_subplots(figure=self, **make_subplots_args)
4153+
41374154

41384155
class BasePlotlyType(object):
41394156
"""

Diff for: 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):

Diff for: 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)

Diff for: 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)