8000 [Bug]: AttributeError: 'NoneType' object has no attribute 'rowspan' with mpl >=3.7 · Issue #25538 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

[Bug]: AttributeError: 'NoneType' object has no attribute 'rowspan' with mpl >=3.7 #25538

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ocefpaf opened this issue Mar 23, 2023 · 4 comments

Comments

@ocefpaf
Copy link
Contributor
ocefpaf commented Mar 23, 2023

Bug summary

With mpl <3.7 this code works the code snippet below works but it is broken in 3.7.0 and 3.7.1. The odd thing is that if I move the colorbar to the last line or if I don't use pandas to the the C plotting it works just fine. I guess there is a bad interaction somewhere that is messing up with the subplots.

Code for reproduction

import matplotlib.pyplot as plt
import pandas as pd

fig = plt.figure()

axes = fig.subplot_mosaic(
    """
    AB
    CC
    """
)

x = [1, 2, 3]
y = [1, 2, 3]

cs0 = axes["A"].scatter(x, y)
cs1 = axes["B"].scatter(x, y)

fig.colorbar(cs0, ax=[axes["A"], axes["B"]], location="right")
axes["C"].plot(x)
pd.DataFrame(x).plot(ax=axes["C"])

Actual outcome

AttributeError                            Traceback (most recent call last)
Cell In[10], line 21
     19 fig.colorbar(cs0, ax=[axes["A"], axes["B"]], location="right")
     20 axes["C"].plot(x)
---> 21 pd.DataFrame(x).plot(ax=axes["C"])
     22 # fig.colorbar(cs0, ax=[axes["A"], axes["B"]], location="right")

File ~/micromamba/envs/TEST/lib/python3.11/site-packages/pandas/plotting/_core.py:1000, in PlotAccessor.__call__(self, *args, **kwargs)
    997             label_name = label_kw or data.columns
    998             data.columns = label_name
-> 1000 return plot_backend.plot(data, kind=kind, **kwargs)

File ~/micromamba/envs/TEST/lib/python3.11/site-packages/pandas/plotting/_matplotlib/__init__.py:71, in plot(data, kind, **kwargs)
     69         kwargs["ax"] = getattr(ax, "left_ax", ax)
     70 plot_obj = PLOT_CLASSES[kind](data, **kwargs)
---> 71 plot_obj.generate()
     72 plot_obj.draw()
     73 return plot_obj.result

File ~/micromamba/envs/TEST/lib/python3.11/site-packages/pandas/plotting/_matplotlib/core.py:455, in MPLPlot.generate(self)
    453 self._add_table()
    454 self._make_legend()
--> 455 self._adorn_subplots()
    457 for ax in self.axes:
    458     self._post_plot_logic_common(ax, self.data)

File ~/micromamba/envs/TEST/lib/python3.11/site-packages/pandas/plotting/_matplotlib/core.py:679, in MPLPlot._adorn_subplots(self)
    677     all_axes = self._get_subplots()
    678     nrows, ncols = self._get_axes_layout()
--> 679     handle_shared_axes(
    680         axarr=all_axes,
    681         nplots=len(all_axes),
    682         naxes=nrows * ncols,
    683         nrows=nrows,
    684         ncols=ncols,
    685         sharex=self.sharex,
    686         sharey=self.sharey,
    687     )
    689 for ax in self.axes:
    690     ax = getattr(ax, "right_ax", ax)

File ~/micromamba/envs/TEST/lib/python3.11/site-packages/pandas/plotting/_matplotlib/tools.py:410, in handle_shared_axes(axarr, nplots, naxes, nrows, ncols, sharex, sharey)
    408 layout = np.zeros((nrows + 1, ncols + 1), dtype=np.bool_)
    409 for ax in axarr:
--> 410     layout[row_num(ax), col_num(ax)] = ax.get_visible()
    412 for ax in axarr:
    413     # only the last row of subplots should get x labels -> all
    414     # other off layout handles the case that the subplot is
    415     # the last in the column, because below is no subplot/gap.
    416     if not layout[row_num(ax) + 1, col_num(ax)]:

File ~/micromamba/envs/TEST/lib/python3.11/site-packages/pandas/plotting/_matplotlib/tools.py:396, in handle_shared_axes.<locals>.<lambda>(x)
    386 def handle_shared_axes(
    387     axarr: Iterable[Axes],
    388     nplots: int,
   (...)
    393     sharey: bool,
    394 ):
    395     if nplots > 1:
--> 396         row_num = lambda x: x.get_subplotspec().rowspan.start
    397         col_num = lambda x: x.get_subplotspec().colspan.start
    399         if compat.mpl_ge_3_4_0():

AttributeError: 'NoneType' object has no attribute 'rowspan'

Expected outcome

Screenshot from 2023-03-23 15-21-12

Additional information

No response

Operating system

No response

Matplotlib Version

3.7.0 and 3.7.1

Matplotlib Backend

module://matplotlib_inline.backend_inline

Python version

3.11

Jupyter version

6.5.3

Installation

conda

@ksunden
Copy link
Member
ksunden commented Mar 23, 2023

This should likely be reported to Pandas.

Drilling down, the problem is precisely that the colorbar is not part of the gridspec, and therefore get_subplotspec returns None.

Since #23573 Subplot is a simple alias of Axes and so all Axes objects have get_subplotspec (but it returns None for axes outside of a gridspec)

#23573 also contains a direct address of this change in behavior.

>>> from matplotlib.axes import Subplot
>>> [ax for ax in fig.get_axes() if isinstance(ax, Subplot)]
[<Axes: label='A'>, <Axes: label='B'>, <Axes: label='C'>, <Axes: label='<colorbar>'>]
>>> [x.get_subplotspec() for x in fig.get_axes()]
[GridSpec(2, 2)[0:1, 0:1], GridSpec(2, 2)[0:1, 1:2], GridSpec(2, 2)[1:2, 0:2], None]

@ocefpaf
Copy link
Contributor Author
ocefpaf commented Mar 23, 2023

This should likely be reported to Pandas.

Makes sense. I ended up reporting here b/c it does work with older mpl versions.

@ocefpaf ocefpaf closed this as completed Mar 23, 2023
@tacaswell
Copy link
Member

This used to work because

    def _get_subplots(self):
        from matplotlib.axes import Subplot

        return [
            ax for ax in self.axes[0].get_figure().get_axes() if isinstance(ax, Subplot)
        ]

used to ignore the colorbar axes because it was not a Subplot.

@tacaswell
Copy link
Member

I could not find a pandas issue, but I opened a PR I think will fix it.

enryH pushed a commit to RasmussenLab/njab that referenced this issue Nov 6, 2023
- colab runs currently on python 3.10 with pandas 1.5.3
  and matplotlib 3.7.1. This leads to an issue with the scatter plot
  in log_reg.py...
  ref: matplotlib/matplotlib#25538
- otherwise code runs in principle now on colab

Next: merge to main and set paths in documentation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants
0