Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 91f58db

Browse files
committed
Merge pull request #5146 from anntzer/figure-subplots
ENH: Move impl. of plt.subplots to Figure.add_subplots. close #5139
2 parents 37182ee + eded075 commit 91f58db

File tree

2 files changed

+137
-99
lines changed

2 files changed

+137
-99
lines changed

lib/matplotlib/figure.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939

4040
from matplotlib.axes import Axes, SubplotBase, subplot_class_factory
4141
from matplotlib.blocking_input import BlockingMouseInput, BlockingKeyMouseInput
42+
from matplotlib.gridspec import GridSpec
4243
from matplotlib.legend import Legend
4344
from matplotlib.patches import Rectangle
4445
from matplotlib.projections import (get_projection_names,
@@ -1011,6 +1012,138 @@ def add_subplot(self, *args, **kwargs):
10111012
a.stale_callback = _stale_figure_callback
10121013
return a
10131014

1015+
def subplots(self, nrows=1, ncols=1, sharex=False, sharey=False,
1016+
squeeze=True, subplot_kw=None, gridspec_kw=None):
1017+
"""
1018+
Add a set of subplots to this figure.
1019+
1020+
Parameters
1021+
----------
1022+
nrows : int, default: 1
1023+
Number of rows of the subplot grid.
1024+
1025+
ncols : int, default: 1
1026+
Number of columns of the subplot grid.
1027+
1028+
sharex : {"none", "all", "row", "col"} or bool, default: False
1029+
If *False*, or "none", each subplot has its own X axis.
1030+
1031+
If *True*, or "all", all subplots will share an X axis, and the x
1032+
tick labels on all but the last row of plots will be invisible.
1033+
1034+
If "col", each subplot column will share an X axis, and the x
1035+
tick labels on all but the last row of plots will be invisible.
1036+
1037+
If "row", each subplot row will share an X axis.
1038+
1039+
sharey : {"none", "all", "row", "col"} or bool, default: False
1040+
If *False*, or "none", each subplot has its own Y axis.
1041+
1042+
If *True*, or "all", all subplots will share an Y axis, and the y
1043+
tick labels on all but the first column of plots will be invisible.
1044+
1045+
If "row", each subplot row will share an Y axis, and the y tick
1046+
labels on all but the first column of plots will be invisible.
1047+
1048+
If "col", each subplot column will share an Y axis.
1049+
1050+
squeeze : bool, default: True
1051+
If *True*, extra dimensions are squeezed out from the returned axes
1052+
array:
1053+
1054+
- if only one subplot is constructed (nrows=ncols=1), the resulting
1055+
single Axes object is returned as a scalar.
1056+
1057+
- for Nx1 or 1xN subplots, the returned object is a 1-d numpy
1058+
object array of Axes objects are returned as numpy 1-d arrays.
1059+
1060+
- for NxM subplots with N>1 and M>1 are returned as a 2d array.
1061+
1062+
If *False*, no squeezing at all is done: the returned object is
1063+
always a 2-d array of Axes instances, even if it ends up being 1x1.
1064+
1065+
subplot_kw : dict, default: {}
1066+
Dict with keywords passed to the
1067+
:meth:`~matplotlib.figure.Figure.add_subplot` call used to create
1068+
each subplots.
1069+
1070+
gridspec_kw : dict, default: {}
1071+
Dict with keywords passed to the
1072+
:class:`~matplotlib.gridspec.GridSpec` constructor used to create
1073+
the grid the subplots are placed on.
1074+
1075+
Returns
1076+
-------
1077+
ax : single Axes object or array of Axes objects
1078+
The added axes. The dimensions of the resulting array can be
1079+
controlled with the squeeze keyword, see above.
1080+
1081+
See Also
1082+
--------
1083+
pyplot.subplots : pyplot API; docstring includes examples.
1084+
"""
1085+
1086+
# for backwards compatibility
1087+
if isinstance(sharex, bool):
1088+
sharex = "all" if sharex else "none"
1089+
if isinstance(sharey, bool):
1090+
sharey = "all" if sharey else "none"
1091+
share_values = ["all", "row", "col", "none"]
1092+
if sharex not in share_values:
1093+
# This check was added because it is very easy to type
1094+
# `subplots(1, 2, 1)` when `subplot(1, 2, 1)` was intended.
1095+
# In most cases, no error will ever occur, but mysterious behavior
1096+
# will result because what was intended to be the subplot index is
1097+
# instead treated as a bool for sharex.
1098+
if isinstance(sharex, int):
1099+
warnings.warn(
1100+
"sharex argument to add_subplots() was an integer. "
1101+
"Did you intend to use add_subplot() (without 's')?")
1102+
1103+
raise ValueError("sharex [%s] must be one of %s" %
1104+
(sharex, share_values))
1105+
if sharey not in share_values:
1106+
raise ValueError("sharey [%s] must be one of %s" %
1107+
(sharey, share_values))
1108+
if subplot_kw is None:
1109+
subplot_kw = {}
1110+
if gridspec_kw is None:
1111+
gridspec_kw = {}
1112+
1113+
gs = GridSpec(nrows, ncols, **gridspec_kw)
1114+
1115+
# Create array to hold all axes.
1116+
axarr = np.empty((nrows, ncols), dtype=object)
1117+
for row in range(nrows):
1118+
for col in range(ncols):
1119+
shared_with = {"none": None, "all": axarr[0, 0],
1120+
"row": axarr[row, 0], "col": axarr[0, col]}
1121+
subplot_kw["sharex"] = shared_with[sharex]
1122+
subplot_kw["sharey"] = shared_with[sharey]
1123+
axarr[row, col] = self.add_subplot(gs[row, col], **subplot_kw)
1124+
1125+
# turn off redundant tick labeling
1126+
if sharex in ["col", "all"]:
1127+
# turn off all but the bottom row
1128+
for ax in axarr[:-1, :].flat:
1129+
for label in ax.get_xticklabels():
1130+
label.set_visible(False)
1131+
ax.xaxis.offsetText.set_visible(False)
1132+
if sharey in ["row", "all"]:
1133+
# turn off all but the first column
1134+
for ax in axarr[:, 1:].flat:
1135+
for label in ax.get_yticklabels():
1136+
label.set_visible(False)
1137+
ax.yaxis.offsetText.set_visible(False)
1138+
1139+
if squeeze:
1140+
# Discarding unneeded dimensions that equal 1. If we only have one
1141+
# subplot, just return it instead of a 1-element array.
1142+
return axarr.item() if axarr.size == 1 else axarr.squeeze()
1143+
else:
1144+
# Returned axis array will be always 2-d, even if nrows=ncols=1.
1145+
return axarr
1146+
10141147
def clf(self, keep_observers=False):
10151148
"""
10161149
Clear the figure.

lib/matplotlib/pyplot.py

Lines changed: 4 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,106 +1142,11 @@ def subplots(nrows=1, ncols=1, sharex=False, sharey=False, squeeze=True,
11421142
# same as
11431143
plt.subplots(2, 2, sharex=True, sharey=True)
11441144
"""
1145-
# for backwards compatibility
1146-
if isinstance(sharex, bool):
1147-
if sharex:
1148-
sharex = "all"
1149-
else:
1150-
sharex = "none"
1151-
if isinstance(sharey, bool):
1152-
if sharey:
1153-
sharey = "all"
1154-
else:
1155-
sharey = "none"
1156-
share_values = ["all", "row", "col", "none"]
1157-
if sharex not in share_values:
1158-
# This check was added because it is very easy to type
1159-
# `subplots(1, 2, 1)` when `subplot(1, 2, 1)` was intended.
1160-
# In most cases, no error will ever occur, but mysterious behavior will
1161-
# result because what was intended to be the subplot index is instead
1162-
# treated as a bool for sharex.
1163-
if isinstance(sharex, int):
1164-
warnings.warn("sharex argument to subplots() was an integer."
1165-
" Did you intend to use subplot() (without 's')?")
1166-
1167-
raise ValueError("sharex [%s] must be one of %s" %
1168-
(sharex, share_values))
1169-
if sharey not in share_values:
1170-
raise ValueError("sharey [%s] must be one of %s" %
1171-
(sharey, share_values))
1172-
if subplot_kw is None:
1173-
subplot_kw = {}
1174-
if gridspec_kw is None:
1175-
gridspec_kw = {}
1176-
11771145
fig = figure(**fig_kw)
1178-
gs = GridSpec(nrows, ncols, **gridspec_kw)
1179-
1180-
# Create empty object array to hold all axes. It's easiest to make it 1-d
1181-
# so we can just append subplots upon creation, and then
1182-
nplots = nrows*ncols
1183-
axarr = np.empty(nplots, dtype=object)
1184-
1185-
# Create first subplot separately, so we can share it if requested
1186-
ax0 = fig.add_subplot(gs[0, 0], **subplot_kw)
1187-
axarr[0] = ax0
1188-
1189-
r, c = np.mgrid[:nrows, :ncols]
1190-
r = r.flatten() * ncols
1191-
c = c.flatten()
1192-
lookup = {
1193-
"none": np.arange(nplots),
1194-
"all": np.zeros(nplots, dtype=int),
1195-
"row": r,
1196-
"col": c,
1197-
}
1198-
sxs = lookup[sharex]
1199-
sys = lookup[sharey]
1200-
1201-
# Note off-by-one counting because add_subplot uses the MATLAB 1-based
1202-
# convention.
1203-
for i in range(1, nplots):
1204-
if sxs[i] == i:
1205-
subplot_kw['sharex'] = None
1206-
else:
1207-
subplot_kw['sharex'] = axarr[sxs[i]]
1208-
if sys[i] == i:
1209-
subplot_kw['sharey'] = None
1210-
else:
1211-
subplot_kw['sharey'] = axarr[sys[i]]
1212-
axarr[i] = fig.add_subplot(gs[i // ncols, i % ncols], **subplot_kw)
1213-
1214-
# returned axis array will be always 2-d, even if nrows=ncols=1
1215-
axarr = axarr.reshape(nrows, ncols)
1216-
1217-
# turn off redundant tick labeling
1218-
if sharex in ["col", "all"] and nrows > 1:
1219-
# turn off all but the bottom row
1220-
for ax in axarr[:-1, :].flat:
1221-
for label in ax.get_xticklabels():
1222-
label.set_visible(False)
1223-
ax.xaxis.offsetText.set_visible(False)
1224-
1225-
if sharey in ["row", "all"] and ncols > 1:
1226-
# turn off all but the first column
1227-
for ax in axarr[:, 1:].flat:
1228-
for label in ax.get_yticklabels():
1229-
label.set_visible(False)
1230-
ax.yaxis.offsetText.set_visible(False)
1231-
1232-
if squeeze:
1233-
# Reshape the array to have the final desired dimension (nrow,ncol),
1234-
# though discarding unneeded dimensions that equal 1. If we only have
1235-
# one subplot, just return it instead of a 1-element array.
1236-
if nplots == 1:
1237-
ret = fig, axarr[0, 0]
1238-
else:
1239-
ret = fig, axarr.squeeze()
1240-
else:
1241-
# returned axis array will be always 2-d, even if nrows=ncols=1
1242-
ret = fig, axarr.reshape(nrows, ncols)
1243-
1244-
return ret
1146+
axs = fig.subplots(nrows=nrows, ncols=ncols, sharex=sharex, sharey=sharey,
1147+
squeeze=squeeze, subplot_kw=subplot_kw,
1148+
gridspec_kw=gridspec_kw)
1149+
return fig, axs
12451150

12461151

12471152
def subplot2grid(shape, loc, rowspan=1, colspan=1, **kwargs):

0 commit comments

Comments
 (0)