Skip to content

Commit 1ce10d6

Browse files
authored
REF: make plotting less stateful (2) (#55850)
* REF: validate_sharex * REF: make plotting less stateful (2) * pylint ignore * mypy fixup
1 parent 8c52003 commit 1ce10d6

File tree

3 files changed

+37
-57
lines changed

3 files changed

+37
-57
lines changed

pandas/plotting/_matplotlib/boxplot.py

-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ def __init__(self, data, return_type: str = "axes", **kwargs) -> None:
8181
# Do not call LinePlot.__init__ which may fill nan
8282
MPLPlot.__init__(self, data, **kwargs) # pylint: disable=non-parent-init-called
8383

84-
def _args_adjust(self) -> None:
8584
if self.subplots:
8685
# Disable label ax sharing. Otherwise, all subplots shows last
8786
# column label

pandas/plotting/_matplotlib/core.py

+25-39
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
from pandas.core.dtypes.common import (
2727
is_any_real_numeric_dtype,
28+
is_bool,
2829
is_float,
2930
is_float_dtype,
3031
is_hashable,
@@ -130,7 +131,7 @@ def __init__(
130131
kind=None,
131132
by: IndexLabel | None = None,
132133
subplots: bool | Sequence[Sequence[str]] = False,
133-
sharex=None,
134+
sharex: bool | None = None,
134135
sharey: bool = False,
135136
use_index: bool = True,
136137
figsize: tuple[float, float] | None = None,
@@ -191,17 +192,7 @@ def __init__(
191192

192193
self.subplots = self._validate_subplots_kwarg(subplots)
193194

194-
if sharex is None:
195-
# if by is defined, subplots are used and sharex should be False
196-
if ax is None and by is None:
197-
self.sharex = True
198-
else:
199-
# if we get an axis, the users should do the visibility
200-
# setting...
201-
self.sharex = False
202-
else:
203-
self.sharex = sharex
204-
195+
self.sharex = self._validate_sharex(sharex, ax, by)
205196
self.sharey = sharey
206197
self.figsize = figsize
207198
self.layout = layout
@@ -275,6 +266,20 @@ def __init__(
275266

276267
self._validate_color_args()
277268

269+
@final
270+
def _validate_sharex(self, sharex: bool | None, ax, by) -> bool:
271+
if sharex is None:
272+
# if by is defined, subplots are used and sharex should be False
273+
if ax is None and by is None: # pylint: disable=simplifiable-if-statement
274+
sharex = True
275+
else:
276+
# if we get an axis, the users should do the visibility
277+
# setting...
278+
sharex = False
279+
elif not is_bool(sharex):
280+
raise TypeError("sharex must be a bool or None")
281+
return bool(sharex)
282+
278283
@final
279284
def _validate_subplots_kwarg(
280285
self, subplots: bool | Sequence[Sequence[str]]
@@ -454,7 +459,6 @@ def draw(self) -> None:
454459

455460
@final
456461
def generate(self) -> None:
457-
self._args_adjust()
458462
self._compute_plot_data()
459463
fig = self._setup_subplots()
460464
self._make_plot(fig)
@@ -466,10 +470,6 @@ def generate(self) -> None:
466470
self._post_plot_logic_common(ax, self.data)
467471
self._post_plot_logic(ax, self.data)
468472

469-
@abstractmethod
470-
def _args_adjust(self) -> None:
471-
pass
472-
473473
@final
474474
def _has_plotted_object(self, ax: Axes) -> bool:
475475
"""check whether ax has data"""
@@ -1326,9 +1326,6 @@ def _make_plot(self, fig: Figure):
13261326
err_kwds["ecolor"] = scatter.get_facecolor()[0]
13271327
ax.errorbar(data[x].values, data[y].values, linestyle="none", **err_kwds)
13281328

1329-
def _args_adjust(self) -> None:
1330-
pass
1331-
13321329

13331330
class HexBinPlot(PlanePlot):
13341331
@property
@@ -1361,9 +1358,6 @@ def _make_plot(self, fig: Figure) -> None:
13611358
def _make_legend(self) -> None:
13621359
pass
13631360

1364-
def _args_adjust(self) -> None:
1365-
pass
1366-
13671361

13681362
class LinePlot(MPLPlot):
13691363
_default_rot = 0
@@ -1529,9 +1523,6 @@ def _update_stacker(cls, ax: Axes, stacking_id, values) -> None:
15291523
elif (values <= 0).all():
15301524
ax._stacker_neg_prior[stacking_id] += values
15311525

1532-
def _args_adjust(self) -> None:
1533-
pass
1534-
15351526
def _post_plot_logic(self, ax: Axes, data) -> None:
15361527
from matplotlib.ticker import FixedLocator
15371528

@@ -1641,9 +1632,6 @@ def _plot( # type: ignore[override]
16411632
res = [rect]
16421633
return res
16431634

1644-
def _args_adjust(self) -> None:
1645-
pass
1646-
16471635
def _post_plot_logic(self, ax: Axes, data) -> None:
16481636
LinePlot._post_plot_logic(self, ax, data)
16491637

@@ -1676,8 +1664,14 @@ def __init__(self, data, **kwargs) -> None:
16761664
kwargs.setdefault("align", "center")
16771665
self.tick_pos = np.arange(len(data))
16781666

1679-
self.bottom = kwargs.pop("bottom", 0)
1680-
self.left = kwargs.pop("left", 0)
1667+
bottom = kwargs.pop("bottom", 0)
1668+
left = kwargs.pop("left", 0)
1669+
if is_list_like(bottom):
1670+
bottom = np.array(bottom)
1671+
if is_list_like(left):
1672+
left = np.array(left)
1673+
self.bottom = bottom
1674+
self.left = left
16811675

16821676
self.log = kwargs.pop("log", False)
16831677
MPLPlot.__init__(self, data, **kwargs)
@@ -1698,12 +1692,6 @@ def __init__(self, data, **kwargs) -> None:
16981692

16991693
self.ax_pos = self.tick_pos - self.tickoffset
17001694

1701-
def _args_adjust(self) -> None:
1702-
if is_list_like(self.bottom):
1703-
self.bottom = np.array(self.bottom)
1704-
if is_list_like(self.left):
1705-
self.left = np.array(self.left)
1706-
17071695
# error: Signature of "_plot" incompatible with supertype "MPLPlot"
17081696
@classmethod
17091697
def _plot( # type: ignore[override]
@@ -1874,8 +1862,6 @@ def __init__(self, data, kind=None, **kwargs) -> None:
18741862
if (data < 0).any().any():
18751863
raise ValueError(f"{self._kind} plot doesn't allow negative values")
18761864
MPLPlot.__init__(self, data, kind=kind, **kwargs)
1877-
1878-
def _args_adjust(self) -> None:
18791865
self.grid = False
18801866
self.logy = False
18811867
self.logx = False

pandas/plotting/_matplotlib/hist.py

+12-17
Original file line numberDiff line numberDiff line change
@@ -58,36 +58,34 @@ def __init__(
5858
bottom: int | np.ndarray = 0,
5959
**kwargs,
6060
) -> None:
61-
self.bins = bins # use mpl default
61+
if is_list_like(bottom):
62+
bottom = np.array(bottom)
6263
self.bottom = bottom
64+
6365
self.xlabel = kwargs.get("xlabel")
6466
self.ylabel = kwargs.get("ylabel")
6567
# Do not call LinePlot.__init__ which may fill nan
6668
MPLPlot.__init__(self, data, **kwargs) # pylint: disable=non-parent-init-called
6769

68-
def _args_adjust(self) -> None:
69-
# calculate bin number separately in different subplots
70-
# where subplots are created based on by argument
71-
if is_integer(self.bins):
70+
self.bins = self._adjust_bins(bins)
71+
72+
def _adjust_bins(self, bins: int | np.ndarray | list[np.ndarray]):
73+
if is_integer(bins):
7274
if self.by is not None:
7375
by_modified = unpack_single_str_list(self.by)
7476
grouped = self.data.groupby(by_modified)[self.columns]
75-
self.bins = [self._calculate_bins(group) for key, group in grouped]
77+
bins = [self._calculate_bins(group, bins) for key, group in grouped]
7678
else:
77-
self.bins = self._calculate_bins(self.data)
78-
79-
if is_list_like(self.bottom):
80-
self.bottom = np.array(self.bottom)
79+
bins = self._calculate_bins(self.data, bins)
80+
return bins
8181

82-
def _calculate_bins(self, data: DataFrame) -> np.ndarray:
82+
def _calculate_bins(self, data: DataFrame, bins) -> np.ndarray:
8383
"""Calculate bins given data"""
8484
nd_values = data.infer_objects(copy=False)._get_numeric_data()
8585
values = np.ravel(nd_values)
8686
values = values[~isna(values)]
8787

88-
hist, bins = np.histogram(
89-
values, bins=self.bins, range=self.kwds.get("range", None)
90-
)
88+
hist, bins = np.histogram(values, bins=bins, range=self.kwds.get("range", None))
9189
return bins
9290

9391
# error: Signature of "_plot" incompatible with supertype "LinePlot"
@@ -211,9 +209,6 @@ def __init__(self, data, bw_method=None, ind=None, **kwargs) -> None:
211209
self.bw_method = bw_method
212210
self.ind = ind
213211

214-
def _args_adjust(self) -> None:
215-
pass
216-
217212
def _get_ind(self, y):
218213
if self.ind is None:
219214
# np.nanmax() and np.nanmin() ignores the missing values

0 commit comments

Comments
 (0)