FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

[Bug]: ax.bar raises for all-nan data on matplotlib 3.6.1 · Issue #24127 · matplotlib/matplotlib · GitHub

Repository navigation

[Bug]: ax.bar raises for all-nan data on matplotlib 3.6.1  #24127

Closed

Description

Bug summary

ax.bar raises an exception in 3.6.1 when passed only nan data. This irrevocably breaks seaborn's histogram function (which draws and then removes a "phantom" bar to trip the color cycle).

Code for reproduction

import numpy as np
import matplotlib.pyplot as plt
f, ax = plt.subplots()
ax.bar([np.nan], [np.nan])

Actual outcome

---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
Cell In [1], line 4
      2 import matplotlib.pyplot as plt
      3 f, ax = plt.subplots()
----> 4 ax.bar([np.nan], [np.nan])[0].get_x()

File ~/miniconda/envs/py310/lib/python3.10/site-packages/matplotlib/__init__.py:1423, in _preprocess_data.<locals>.inner(ax, data, *args, **kwargs)
   1420 @functools.wraps(func)
   1421 def inner(ax, *args, data=None, **kwargs):
   1422     if data is None:
-> 1423         return func(ax, *map(sanitize_sequence, args), **kwargs)
   1425     bound = new_sig.bind(ax, *args, **kwargs)
   1426     auto_label = (bound.arguments.get(label_namer)
   1427                   or bound.kwargs.get(label_namer))

File ~/miniconda/envs/py310/lib/python3.10/site-packages/matplotlib/axes/_axes.py:2373, in Axes.bar(self, x, height, width, bottom, align, **kwargs)
   2371 x0 = x
   2372 x = np.asarray(self.convert_xunits(x))
-> 2373 width = self._convert_dx(width, x0, x, self.convert_xunits)
   2374 if xerr is not None:
   2375     xerr = self._convert_dx(xerr, x0, x, self.convert_xunits)

File ~/miniconda/envs/py310/lib/python3.10/site-packages/matplotlib/axes/_axes.py:2182, in Axes._convert_dx(dx, x0, xconv, convert)
   2170 try:
   2171     # attempt to add the width to x0; this works for
   2172     # datetime+timedelta, for instance
   (...)
   2179     # removes the units from unit packages like `pint` that
   2180     # wrap numpy arrays.
   2181     try:
-> 2182         x0 = cbook._safe_first_finite(x0)
   2183     except (TypeError, IndexError, KeyError):
   2184         pass

File ~/miniconda/envs/py310/lib/python3.10/site-packages/matplotlib/cbook/__init__.py:1749, in _safe_first_finite(obj, skip_nonfinite)
   1746     raise RuntimeError("matplotlib does not "
   1747                        "support generators as input")
   1748 else:
-> 1749     return next(val for val in obj if safe_isfinite(val))

StopIteration: 

Expected outcome

On 3.6.0 this returns a BarCollection with one Rectangle, having nan for x and height.

Additional information

I assume it's related to this bullet in the release notes:

  • Fix barplot being empty when first element is NaN

But I don't know the context for it to investigate further (could these link to PRs?)

Further debugging:

ax.bar([np.nan], [0])  # Raises
ax.bar([0], [np.nan])  # Works

So it's about the x position specifically.

Operating system

Macos

Matplotlib Version

3.6.1

Matplotlib Backend

No response

Python version

No response

Jupyter version

No response

Installation

pip

Activity

  1. changed the title [-][Bug]: Matplotlib 3.6.1 breaks [/-] [+][Bug]: ax.bar raises for all-nan data on matplotlib 3.6.1 [/+] on Oct 8, 2022
  2. oscargus commented on Oct 8, 2022

    Member

    This is the PR in question: #23751 (although I have not checked is that is causing it).

  3. added this to the v3.6.2 milestone on Oct 8, 2022
  4. mwaskom commented on Oct 8, 2022

    Author

    Thanks @oscargus that indeed looks like the culprit: it asks for the "next" finite value and does not handle the StopIteration exception that you get if there isn't one.

  5. tacaswell commented on Oct 8, 2022

    Member

    which draws and then removes a "phantom" bar to trip the color cycle

    We should definitely fix this regression, but is there a better way for seaborn to be managing the colors that does not require adding and removing artists? I assume you use np.nan to avoid triggering any of the autoscaling?

  6. mwaskom commented on Oct 8, 2022

    Author

    We should definitely fix this regression, but is there a better way for seaborn to be managing the colors that does not require adding and removing artists?

    Definitely open to that but none that I am aware of! I don't think there's a public API for advancing the property cycle? AFAIK one would need to do something like ax._get_patches_for_fill.get_next_color().

    I assume you use np.nan to avoid triggering any of the autoscaling?

    Yep, exactly. Actually in most cases I just pass empty data, but ax.bar([], []) doesn't return an artist (just an empty BarContainer so it doesn't work with that pattern. See here for more details: https://github.com/mwaskom/seaborn/blob/5386adc5a482ef3d0aef958ebf37d39ce0b06b88/seaborn/utils.py#L138

  7. jklymak commented on Oct 8, 2022

    Member

    Just as a meta comment I guess this should not have been milestones so aggressively? The pr fixed a bug, but an old one so maybe could have waited for 3.7?

  8. oscargus commented on Oct 8, 2022

    Member

    If I understand correctly, it did work in 3.6.0 for the all-nan case, but not for a leading nan (and other non-nan values). So although a bug was fixed in 3.6.1, this was introduced there as well.

    (If my understanding is wrong then it could for sure have waited.)

  9. tacaswell commented on Oct 12, 2022

    Member
    ✔ 15:28:08 $ git diff
    diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py
    index fdac0f3560..de4a99f71d 100644
    --- a/lib/matplotlib/axes/_axes.py
    +++ b/lib/matplotlib/axes/_axes.py
    @@ -2182,11 +2182,19 @@ class Axes(_AxesBase):
                     x0 = cbook._safe_first_finite(x0)
                 except (TypeError, IndexError, KeyError):
                     pass
    +            except StopIteration:
    +                # this means we found no finite element, fall back to first
    +                # element unconditionally
    +                x0 = cbook.safe_first_element(x0)
    
                 try:
                     x = cbook._safe_first_finite(xconv)
                 except (TypeError, IndexError, KeyError):
                     x = xconv
    +            except StopIteration:
    +                # this means we found no finite element, fall back to first
    +                # element unconditionally
    +                x = cbook.safe_first_element(xconv)
    
                 delist = False
                 if not np.iterable(dx):
    

    I think this is the fix, need to commit it and add a test.


    My memory of this was that this was a 3.6 regression from 3.5 but looking at the linked issue that was clearly wrong.

  10. added 2 commits that reference this issue on Oct 12, 2022
    5d1f31e
    7c5b99f
  11. added a commit that references this issue on Oct 18, 2022
    a8f73ba
  12. added a commit that references this issue on Oct 24, 2022
    bd481e8
  13. added a commit that references this issue on Dec 19, 2022
    e7a2bcc
  14. sophiamaedler commented on Apr 12, 2024

    So interestingly I am still encountering this error with a recent version of matplotlib on MacOS. On a linux based system it is working as expected.

    Test code:

    import matplotlib
    print('matplotlib: {}'.format(matplotlib.__version__))
    
    import numpy as np
    import matplotlib.pyplot as plt
    f, ax = plt.subplots()
    ax.bar([np.nan], [np.nan])
    

    Output Linux:

    Output MacOS:

    matplotlib: 3.8.4
    ---------------------------------------------------------------------------
    StopIteration                             Traceback (most recent call last)
    Cell In[7], line 7
          5 import matplotlib.pyplot as plt
          6 f, ax = plt.subplots()
    ----> 7 ax.bar([np.nan], [np.nan])
    
    File ~/mambaforge/envs/stitching/lib/python3.10/site-packages/matplotlib/__init__.py:1465, in _preprocess_data.<locals>.inner(ax, data, *args, **kwargs)
       1462 @functools.wraps(func)
       1463 def inner(ax, *args, data=None, **kwargs):
       1464     if data is None:
    -> 1465         return func(ax, *map(sanitize_sequence, args), **kwargs)
       1467     bound = new_sig.bind(ax, *args, **kwargs)
       1468     auto_label = (bound.arguments.get(label_namer)
       1469                   or bound.kwargs.get(label_namer))
    
    File ~/mambaforge/envs/stitching/lib/python3.10/site-packages/matplotlib/axes/_axes.py:2451, in Axes.bar(self, x, height, width, bottom, align, **kwargs)
       2449 x0 = x
       2450 x = np.asarray(self.convert_xunits(x))
    -> 2451 width = self._convert_dx(width, x0, x, self.convert_xunits)
       2452 if xerr is not None:
       2453     xerr = self._convert_dx(xerr, x0, x, self.convert_xunits)
    
    File ~/mambaforge/envs/stitching/lib/python3.10/site-packages/matplotlib/axes/_axes.py:2244, in Axes._convert_dx(dx, x0, xconv, convert)
       2232 try:
    ...
       1713                        "support generators as input")
       1714 else:
    -> 1715     return next(val for val in obj if safe_isfinite(val))
    
    StopIteration:
    

    Here the info to the installed python versions

    Linux

    Python version
    3.10.14 | packaged by conda-forge | (main, Mar 20 2024, 12:45:18) [GCC 12.3.0]
    Version info.
    sys.version_info(major=3, minor=10, micro=14, releaselevel='final', serial=0)
    

    MacOS:

    Python version
    3.10.11 | packaged by conda-forge | (main, May 10 2023, 19:01:19) [Clang 14.0.6 ]
    Version info.
    sys.version_info(major=3, minor=10, micro=11, releaselevel='final', serial=0)
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL