Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/2.3.x' into backport-59433
Browse files Browse the repository at this point in the history
  • Loading branch information
jorisvandenbossche committed Dec 18, 2024
2 parents 60c6f84 + eb22bf8 commit 3efcd72
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 23 deletions.
5 changes: 4 additions & 1 deletion pandas/plotting/_matplotlib/boxplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
)
import warnings

import matplotlib as mpl
from matplotlib.artist import setp
import numpy as np

Expand All @@ -20,6 +21,7 @@

import pandas as pd
import pandas.core.common as com
from pandas.util.version import Version

from pandas.io.formats.printing import pprint_thing
from pandas.plotting._matplotlib.core import (
Expand Down Expand Up @@ -54,7 +56,8 @@ def _set_ticklabels(ax: Axes, labels: list[str], is_vertical: bool, **kwargs) ->
ticks = ax.get_xticks() if is_vertical else ax.get_yticks()
if len(ticks) != len(labels):
i, remainder = divmod(len(ticks), len(labels))
assert remainder == 0, remainder
if Version(mpl.__version__) < Version("3.10"):
assert remainder == 0, remainder
labels *= i
if is_vertical:
ax.set_xticklabels(labels, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion pandas/plotting/_matplotlib/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def format_date_labels(ax: Axes, rot) -> None:
fig = ax.get_figure()
if fig is not None:
# should always be a Figure but can technically be None
maybe_adjust_figure(fig, bottom=0.2)
maybe_adjust_figure(fig, bottom=0.2) # type: ignore[arg-type]


def table(
Expand Down
41 changes: 33 additions & 8 deletions pandas/tests/plotting/frame/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -1059,41 +1059,66 @@ def test_boxplot_series_positions(self, hist_df):
tm.assert_numpy_array_equal(ax.xaxis.get_ticklocs(), positions)
assert len(ax.lines) == 7 * len(numeric_cols)

@pytest.mark.filterwarnings("ignore:set_ticklabels:UserWarning")
@pytest.mark.xfail(
Version(mpl.__version__) >= Version("3.10"),
reason="Fails starting with matplotlib 3.10",
)
def test_boxplot_vertical(self, hist_df):
df = hist_df
numeric_cols = df._get_numeric_data().columns
labels = [pprint_thing(c) for c in numeric_cols]

# if horizontal, yticklabels are rotated
ax = df.plot.box(rot=50, fontsize=8, vert=False)
kwargs = (
{"vert": False}
if Version(mpl.__version__) < Version("3.10")
else {"orientation": "horizontal"}
)
ax = df.plot.box(rot=50, fontsize=8, **kwargs)
_check_ticks_props(ax, xrot=0, yrot=50, ylabelsize=8)
_check_text_labels(ax.get_yticklabels(), labels)
assert len(ax.lines) == 7 * len(numeric_cols)

@pytest.mark.filterwarnings("ignore:Attempt:UserWarning")
@pytest.mark.filterwarnings("ignore::UserWarning")
@pytest.mark.xfail(
Version(mpl.__version__) >= Version("3.10"),
reason="Fails starting with matplotlib version 3.10",
)
def test_boxplot_vertical_subplots(self, hist_df):
df = hist_df
numeric_cols = df._get_numeric_data().columns
labels = [pprint_thing(c) for c in numeric_cols]
kwargs = (
{"vert": False}
if Version(mpl.__version__) < Version("3.10")
else {"orientation": "horizontal"}
)
axes = _check_plot_works(
df.plot.box,
default_axes=True,
subplots=True,
vert=False,
logx=True,
df.plot.box, default_axes=True, subplots=True, logx=True, **kwargs
)
_check_axes_shape(axes, axes_num=3, layout=(1, 3))
_check_ax_scales(axes, xaxis="log")
for ax, label in zip(axes, labels):
_check_text_labels(ax.get_yticklabels(), [label])
assert len(ax.lines) == 7

@pytest.mark.filterwarnings("ignore:set_ticklabels:UserWarning")
@pytest.mark.xfail(
Version(mpl.__version__) >= Version("3.10"),
reason="Fails starting with matplotlib 3.10",
)
def test_boxplot_vertical_positions(self, hist_df):
df = hist_df
numeric_cols = df._get_numeric_data().columns
labels = [pprint_thing(c) for c in numeric_cols]
positions = np.array([3, 2, 8])
ax = df.plot.box(positions=positions, vert=False)
kwargs = (
{"vert": False}
if Version(mpl.__version__) < Version("3.10")
else {"orientation": "horizontal"}
)
ax = df.plot.box(positions=positions, **kwargs)
_check_text_labels(ax.get_yticklabels(), labels)
tm.assert_numpy_array_equal(ax.yaxis.get_ticklocs(), positions)
assert len(ax.lines) == 7 * len(numeric_cols)
Expand Down
51 changes: 38 additions & 13 deletions pandas/tests/plotting/test_boxplot_method.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
""" Test cases for .boxplot method """

from __future__ import annotations

import itertools
import string

Expand All @@ -22,6 +24,7 @@
_check_ticks_props,
_check_visible,
)
from pandas.util.version import Version

from pandas.io.formats.printing import pprint_thing

Expand All @@ -35,6 +38,17 @@ def _check_ax_limits(col, ax):
assert y_max >= col.max()


if Version(mpl.__version__) < Version("3.10"):
verts: list[dict[str, bool | str]] = [{"vert": False}, {"vert": True}]
else:
verts = [{"orientation": "horizontal"}, {"orientation": "vertical"}]


@pytest.fixture(params=verts)
def vert(request):
return request.param


class TestDataFramePlots:
def test_stacked_boxplot_set_axis(self):
# GH2980
Expand Down Expand Up @@ -315,7 +329,7 @@ def test_specified_props_kwd(self, props, expected):

assert result[expected][0].get_color() == "C1"

@pytest.mark.parametrize("vert", [True, False])
@pytest.mark.filterwarnings("ignore:set_ticklabels:UserWarning")
def test_plot_xlabel_ylabel(self, vert):
df = DataFrame(
{
Expand All @@ -325,11 +339,11 @@ def test_plot_xlabel_ylabel(self, vert):
}
)
xlabel, ylabel = "x", "y"
ax = df.plot(kind="box", vert=vert, xlabel=xlabel, ylabel=ylabel)
ax = df.plot(kind="box", xlabel=xlabel, ylabel=ylabel, **vert)
assert ax.get_xlabel() == xlabel
assert ax.get_ylabel() == ylabel

@pytest.mark.parametrize("vert", [True, False])
@pytest.mark.filterwarnings("ignore:set_ticklabels:UserWarning")
def test_plot_box(self, vert):
# GH 54941
rng = np.random.default_rng(2)
Expand All @@ -338,14 +352,14 @@ def test_plot_box(self, vert):

xlabel, ylabel = "x", "y"
_, axs = plt.subplots(ncols=2, figsize=(10, 7), sharey=True)
df1.plot.box(ax=axs[0], vert=vert, xlabel=xlabel, ylabel=ylabel)
df2.plot.box(ax=axs[1], vert=vert, xlabel=xlabel, ylabel=ylabel)
df1.plot.box(ax=axs[0], xlabel=xlabel, ylabel=ylabel, **vert)
df2.plot.box(ax=axs[1], xlabel=xlabel, ylabel=ylabel, **vert)
for ax in axs:
assert ax.get_xlabel() == xlabel
assert ax.get_ylabel() == ylabel
mpl.pyplot.close()

@pytest.mark.parametrize("vert", [True, False])
@pytest.mark.filterwarnings("ignore:set_ticklabels:UserWarning")
def test_boxplot_xlabel_ylabel(self, vert):
df = DataFrame(
{
Expand All @@ -355,11 +369,11 @@ def test_boxplot_xlabel_ylabel(self, vert):
}
)
xlabel, ylabel = "x", "y"
ax = df.boxplot(vert=vert, xlabel=xlabel, ylabel=ylabel)
ax = df.boxplot(xlabel=xlabel, ylabel=ylabel, **vert)
assert ax.get_xlabel() == xlabel
assert ax.get_ylabel() == ylabel

@pytest.mark.parametrize("vert", [True, False])
@pytest.mark.filterwarnings("ignore:set_ticklabels:UserWarning")
def test_boxplot_group_xlabel_ylabel(self, vert):
df = DataFrame(
{
Expand All @@ -369,24 +383,35 @@ def test_boxplot_group_xlabel_ylabel(self, vert):
}
)
xlabel, ylabel = "x", "y"
ax = df.boxplot(by="group", vert=vert, xlabel=xlabel, ylabel=ylabel)
ax = df.boxplot(by="group", xlabel=xlabel, ylabel=ylabel, **vert)
for subplot in ax:
assert subplot.get_xlabel() == xlabel
assert subplot.get_ylabel() == ylabel
mpl.pyplot.close()

@pytest.mark.parametrize("vert", [True, False])
def test_boxplot_group_no_xlabel_ylabel(self, vert):
@pytest.mark.filterwarnings("ignore:set_ticklabels:UserWarning")
def test_boxplot_group_no_xlabel_ylabel(self, vert, request):
if Version(mpl.__version__) >= Version("3.10") and vert == {
"orientation": "horizontal"
}:
request.applymarker(
pytest.mark.xfail(reason=f"{vert} fails starting with matplotlib 3.10")
)
df = DataFrame(
{
"a": np.random.default_rng(2).standard_normal(10),
"b": np.random.default_rng(2).standard_normal(10),
"group": np.random.default_rng(2).choice(["group1", "group2"], 10),
}
)
ax = df.boxplot(by="group", vert=vert)
ax = df.boxplot(by="group", **vert)
for subplot in ax:
target_label = subplot.get_xlabel() if vert else subplot.get_ylabel()
target_label = (
subplot.get_xlabel()
if vert == {"vert": True} # noqa: PLR1714
or vert == {"orientation": "vertical"}
else subplot.get_ylabel()
)
assert target_label == pprint_thing(["group"])
mpl.pyplot.close()

Expand Down

0 comments on commit 3efcd72

Please sign in to comment.