Skip to content

BUG: MatplotlibDeprecationWarning: The is_first_col function was deprecated in Matplotlib 3.4 #40714

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
arnaujc91 opened this issue Mar 31, 2021 · 5 comments · Fixed by #40718
Labels
Bug CI Continuous Integration Dependencies Required and optional dependencies Visualization plotting
Milestone

Comments

@arnaujc91
Copy link

import pandas as pd
from matplotlib import pyplot as plt

series = [pd.Series([1,2,3,4]) for _ in range(4)]

nrow, ncol = 2, 2
fig, axes = plt.subplots(nrow, ncol)
axes = axes.reshape(-1)
for i, s in enumerate(series):
    s.plot(ax=axes[i])

plt.tight_layout()

Problem description

After executing the previous code the following message from Matplotlib is shown:

The is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.
  if ax.is_first_col():
@arnaujc91 arnaujc91 added Bug Needs Triage Issue that has not been reviewed by a pandas team member labels Mar 31, 2021
@lithomas1 lithomas1 added Visualization plotting Dependencies Required and optional dependencies and removed Needs Triage Issue that has not been reviewed by a pandas team member labels Mar 31, 2021
@lithomas1 lithomas1 added this to the 1.3 milestone Mar 31, 2021
@lithomas1 lithomas1 added the CI Continuous Integration label Mar 31, 2021
@lithomas1
Copy link
Member

Hi @arnaujc91,
Thanks for the bug report. I can confirm that this happens with the latest matplotlib, and I've spotted some failing tests in our CI related to this.
e.g. https://github.com/pandas-dev/pandas/pull/40713/checks?check_run_id=2240746140

______________ TestDataFramePlotsSubplots.test_subplots_warnings _______________
[gw1] linux -- Python 3.8.8 /home/runner/miniconda3/envs/pandas-dev/bin/python

self = <pandas.tests.plotting.frame.test_frame_subplots.TestDataFramePlotsSubplots object at 0x7f8d83a6edf0>

    def test_subplots_warnings(self):
        # GH 9464
        with tm.assert_produces_warning(None):
            df = DataFrame(np.random.randn(100, 4))
            df.plot(subplots=True, layout=(3, 2))
    
            df = DataFrame(
                np.random.randn(100, 4), index=date_range("1/1/2000", periods=100)
            )
>           df.plot(subplots=True, layout=(3, 2))

pandas/tests/plotting/frame/test_frame_subplots.py:264: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../miniconda3/envs/pandas-dev/lib/python3.8/contextlib.py:120: in __exit__
    next(self.gen)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def _assert_caught_no_extra_warnings(
        *,
        caught_warnings: Sequence[warnings.WarningMessage],
Warning: xpected_warning: Optional[Union[Type[Warning], bool]],
    ) -> None:
        """Assert that no extra warnings apart from the expected ones are caught."""
        extra_warnings = []
    
        for actual_warning in caught_warnings:
            if _is_unexpected_warning(actual_warning, expected_warning):
                extra_warnings.append(
                    (
                        actual_warning.category.__name__,
                        actual_warning.message,
                        actual_warning.filename,
                        actual_warning.lineno,
                    )
                )
    
        if extra_warnings:
>           raise AssertionError(f"Caused unexpected warning(s): {repr(extra_warnings)}")
E           AssertionError: Caused unexpected warning(s): [('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426)]

pandas/_testing/_warnings.py:155: AssertionError
______________________ TestDataFramePlots.test_pie_df_nan ______________________
[gw0] linux -- Python 3.8.8 /home/runner/miniconda3/envs/pandas-dev/bin/python

self = <pandas.tests.plotting.frame.test_frame.TestDataFramePlots object at 0x7f65e95a4fd0>

    def test_pie_df_nan(self):
        import matplotlib as mpl
    
        df = DataFrame(np.random.rand(4, 4))
        for i in range(4):
            df.iloc[i, i] = np.nan
        fig, axes = self.plt.subplots(ncols=4)
    
        # GH 37668
        kwargs = {}
        if mpl.__version__ >= "3.3":
            kwargs = {"normalize": True}
    
        with tm.assert_produces_warning(None):
>           df.plot.pie(subplots=True, ax=axes, legend=True, **kwargs)

pandas/tests/plotting/frame/test_frame.py:1523: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../miniconda3/envs/pandas-dev/lib/python3.8/contextlib.py:120: in __exit__
    next(self.gen)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def _assert_caught_no_extra_warnings(
        *,
        caught_warnings: Sequence[warnings.WarningMessage],
Warning: xpected_warning: Optional[Union[Type[Warning], bool]],
    ) -> None:
        """Assert that no extra warnings apart from the expected ones are caught."""
        extra_warnings = []
    
        for actual_warning in caught_warnings:
            if _is_unexpected_warning(actual_warning, expected_warning):
                extra_warnings.append(
                    (
                        actual_warning.category.__name__,
                        actual_warning.message,
                        actual_warning.filename,
                        actual_warning.lineno,
                    )
                )
    
        if extra_warnings:
>           raise AssertionError(f"Caused unexpected warning(s): {repr(extra_warnings)}")
E           AssertionError: Caused unexpected warning(s): [('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426), ('MatplotlibDeprecationWarning', MatplotlibDeprecationWarning('\nThe is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.'), '/home/runner/work/pandas/pandas/pandas/plotting/_matplotlib/tools.py', 426)]

pandas/_testing/_warnings.py:155: AssertionError

The culprit seems to be here.

if ax.is_first_col():

@arnaujc91
Copy link
Author

Indeed, I just changed this line of code in my local version of Pandas and everything seems to work well. I will try to create a PR tomorrow when I have more time.

Thank you!

@arnaujc91
Copy link
Author

Hi @lithomas1,
I tried to create a PR but it seems one test is doing something odd.

=================================== FAILURES ===================================
_________________ TestDataFramePlots.test_plot_scatter_with_c __________________
[gw0] linux -- Python 3.8.8 /usr/share/miniconda/envs/pandas-dev/bin/python

self = <pandas.tests.plotting.frame.test_frame.TestDataFramePlots object at 0x7f955b4d8c40>

    def test_plot_scatter_with_c(self):
        df = DataFrame(
            np.random.randn(6, 4),
            index=list(string.ascii_letters[:6]),
            columns=["x", "y", "z", "four"],
        )
    
        axes = [df.plot.scatter(x="x", y="y", c="z"), df.plot.scatter(x=0, y=1, c=2)]
        for ax in axes:
            # default to Greys
            assert ax.collections[0].cmap.name == "Greys"
    
            # n.b. there appears to be no public method
            # to get the colorbar label
>           assert ax.collections[0].colorbar._label == "z"
E           AttributeError: 'Colorbar' object has no attribute '_label'

pandas/tests/plotting/frame/test_frame.py:763: AttributeError

it is an error which belongs to the test, not to anything I have changed in particular. So I assume it should fail for any PR.

@attack68
Copy link
Contributor

attack68 commented Apr 1, 2021

        # n.b. there appears to be no public method
        # to get the colorbar label
      assert ax.collections[0].colorbar._label == "z"

E AttributeError: 'Colorbar' object has no attribute '_label'

recent matplotlib docs seem to suggest there is now a public attribute label, perhaps remove the _ and try again?

@jreback jreback mentioned this issue Apr 1, 2021
4 tasks
@arnaujc91
Copy link
Author

arnaujc91 commented Apr 1, 2021

Hi @jreback and @attack68,

I think the issue can be solved replacing

assert ax.collections[0].colorbar._label == "z"

with

assert ax.collections[0].colorbar.ax.get_ylabel() == "z" or ax.collections[0].colorbar.ax.get_xlabel() == "z"

This worked for me. As you can see in the original code from colorbar (set_label method):

### More code from the original function 'set_label" ###
        if self.orientation == "vertical":
            self.ax.set_ylabel(label, loc=loc, **kwargs)
        else:
            self.ax.set_xlabel(label, loc=loc, **kwargs)
        self.stale = True

the label to be checked depends on this self.orientation. It seems there is no label attribute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug CI Continuous Integration Dependencies Required and optional dependencies Visualization plotting
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants