diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index d24c595cacab5..539938a153782 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -384,7 +384,7 @@ Plotting ^^^^^^^^ - Bug in :func:`scatter_matrix` raising when 2d ``ax`` argument passed (:issue:`16253`) -- +- Prevent warnings when matplotlib's ``constrained_layout`` is enabled (:issue:`25261`) - Groupby/resample/rolling diff --git a/pandas/plotting/_matplotlib/boxplot.py b/pandas/plotting/_matplotlib/boxplot.py index 1fb75cd9d13e4..eec4c409a81b6 100644 --- a/pandas/plotting/_matplotlib/boxplot.py +++ b/pandas/plotting/_matplotlib/boxplot.py @@ -16,7 +16,11 @@ from pandas.io.formats.printing import pprint_thing from pandas.plotting._matplotlib.core import LinePlot, MPLPlot from pandas.plotting._matplotlib.style import get_standard_colors -from pandas.plotting._matplotlib.tools import create_subplots, flatten_axes +from pandas.plotting._matplotlib.tools import ( + create_subplots, + flatten_axes, + maybe_adjust_figure, +) if TYPE_CHECKING: from matplotlib.axes import Axes @@ -229,7 +233,7 @@ def _grouped_plot_by_column( byline = by[0] if len(by) == 1 else by fig.suptitle(f"Boxplot grouped by {byline}") - fig.subplots_adjust(bottom=0.15, top=0.9, left=0.1, right=0.9, wspace=0.2) + maybe_adjust_figure(fig, bottom=0.15, top=0.9, left=0.1, right=0.9, wspace=0.2) return result @@ -436,7 +440,7 @@ def boxplot_frame_groupby( ) ax.set_title(pprint_thing(key)) ret.loc[key] = d - fig.subplots_adjust(bottom=0.15, top=0.9, left=0.1, right=0.9, wspace=0.2) + maybe_adjust_figure(fig, bottom=0.15, top=0.9, left=0.1, right=0.9, wspace=0.2) else: keys, frames = zip(*grouped) if grouped.axis == 0: diff --git a/pandas/plotting/_matplotlib/hist.py b/pandas/plotting/_matplotlib/hist.py index e65834b2a8798..018d19e81d5c4 100644 --- a/pandas/plotting/_matplotlib/hist.py +++ b/pandas/plotting/_matplotlib/hist.py @@ -13,6 +13,7 @@ from pandas.plotting._matplotlib.tools import ( create_subplots, flatten_axes, + maybe_adjust_figure, set_ticks_props, ) @@ -296,8 +297,8 @@ def plot_group(group, ax): axes, xlabelsize=xlabelsize, xrot=xrot, ylabelsize=ylabelsize, yrot=yrot ) - fig.subplots_adjust( - bottom=0.15, top=0.9, left=0.1, right=0.9, hspace=0.5, wspace=0.3 + maybe_adjust_figure( + fig, bottom=0.15, top=0.9, left=0.1, right=0.9, hspace=0.5, wspace=0.3 ) return axes @@ -456,6 +457,6 @@ def hist_frame( set_ticks_props( axes, xlabelsize=xlabelsize, xrot=xrot, ylabelsize=ylabelsize, yrot=yrot ) - fig.subplots_adjust(wspace=0.3, hspace=0.3) + maybe_adjust_figure(fig, wspace=0.3, hspace=0.3) return axes diff --git a/pandas/plotting/_matplotlib/misc.py b/pandas/plotting/_matplotlib/misc.py index d25b86fb8f5b8..01ac3de4ff3bb 100644 --- a/pandas/plotting/_matplotlib/misc.py +++ b/pandas/plotting/_matplotlib/misc.py @@ -11,7 +11,12 @@ from pandas.io.formats.printing import pprint_thing from pandas.plotting._matplotlib.style import get_standard_colors -from pandas.plotting._matplotlib.tools import create_subplots, set_ticks_props +from pandas.plotting._matplotlib.tools import ( + create_subplots, + do_adjust_figure, + maybe_adjust_figure, + set_ticks_props, +) if TYPE_CHECKING: from matplotlib.axes import Axes @@ -39,7 +44,7 @@ def scatter_matrix( fig, axes = create_subplots(naxes=naxes, figsize=figsize, ax=ax, squeeze=False) # no gaps between subplots - fig.subplots_adjust(wspace=0, hspace=0) + maybe_adjust_figure(fig, wspace=0, hspace=0) mask = notna(df) @@ -329,7 +334,8 @@ def bootstrap_plot( for axis in axes: plt.setp(axis.get_xticklabels(), fontsize=8) plt.setp(axis.get_yticklabels(), fontsize=8) - plt.tight_layout() + if do_adjust_figure(fig): + plt.tight_layout() return fig diff --git a/pandas/plotting/_matplotlib/tools.py b/pandas/plotting/_matplotlib/tools.py index e1315aad36c29..df94b71f5e7a9 100644 --- a/pandas/plotting/_matplotlib/tools.py +++ b/pandas/plotting/_matplotlib/tools.py @@ -19,17 +19,31 @@ if TYPE_CHECKING: from matplotlib.axes import Axes from matplotlib.axis import Axis + from matplotlib.figure import Figure from matplotlib.lines import Line2D from matplotlib.table import Table +def do_adjust_figure(fig: Figure): + """Whether fig has constrained_layout enabled.""" + if not hasattr(fig, "get_constrained_layout"): + return False + return not fig.get_constrained_layout() + + +def maybe_adjust_figure(fig: Figure, *args, **kwargs): + """Call fig.subplots_adjust unless fig has constrained_layout enabled.""" + if do_adjust_figure(fig): + fig.subplots_adjust(*args, **kwargs) + + def format_date_labels(ax: Axes, rot): # mini version of autofmt_xdate for label in ax.get_xticklabels(): label.set_ha("right") label.set_rotation(rot) fig = ax.get_figure() - fig.subplots_adjust(bottom=0.2) + maybe_adjust_figure(fig, bottom=0.2) def table( diff --git a/pandas/tests/plotting/frame/test_frame_subplots.py b/pandas/tests/plotting/frame/test_frame_subplots.py index 2e0eecbeaacaa..049f357a4647f 100644 --- a/pandas/tests/plotting/frame/test_frame_subplots.py +++ b/pandas/tests/plotting/frame/test_frame_subplots.py @@ -482,6 +482,19 @@ def test_subplots_sharex_false(self): tm.assert_numpy_array_equal(axs[0].get_xticks(), expected_ax1) tm.assert_numpy_array_equal(axs[1].get_xticks(), expected_ax2) + def test_subplots_constrained_layout(self): + # GH 25261 + idx = date_range(start="now", periods=10) + df = DataFrame(np.random.rand(10, 3), index=idx) + kwargs = {} + if hasattr(self.plt.Figure, "get_constrained_layout"): + kwargs["constrained_layout"] = True + fig, axes = self.plt.subplots(2, **kwargs) + with tm.assert_produces_warning(None): + df.plot(ax=axes[0]) + with tm.ensure_clean(return_filelike=True) as path: + self.plt.savefig(path) + @pytest.mark.parametrize( "index_name, old_label, new_label", [