Skip to content

broken_barh appears not to work with datetime/timedelta objects #12862

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
pfmoore opened this issue Nov 21, 2018 · 1 comment · Fixed by #12903
Closed

broken_barh appears not to work with datetime/timedelta objects #12862

pfmoore opened this issue Nov 21, 2018 · 1 comment · Fixed by #12903

Comments

@pfmoore
Copy link

pfmoore commented Nov 21, 2018

Bug report

Bug summary

The Axis.broken_barh function takes an xranges parameter described as "The x-positions and extends of the rectangles". But if I'm plotting datetime values on the axis, it appears impossible to supply an extent value of a type that the function can deal with.

Using datetime.timedelta raises an exception AttributeError: 'datetime.timedelta' object has no attribute 'toordinal', as does using an integer. Using a datetime value causes the bar to extend too far (which I guess isn't surprising, as toordinal on a datetime will not give a duration).

Code for reproduction

import matplotlib.pyplot as plt
from datetime import datetime, timedelta

lo = datetime.fromisoformat("2018-11-09 20:00")
hi = datetime.fromisoformat("2018-11-09 22:00")

fig, ax = plt.subplots()

ax.set_xlim(lo, hi)
ax.set_ylim(0, 30)
ax.broken_barh([(lo, timedelta(hours=1))], (10, 20))

plt.show()

Actual outcome

Traceback (most recent call last):
  File ".\problem.py", line 11, in <module>
    ax.broken_barh([(lo, timedelta(hours=1))], (10, 20))
  File "C:\...\lib\site-packages\matplotlib\__init__.py", line 1810, in inner
    return func(ax, *args, **kwargs)
  File "C:\...\lib\site-packages\matplotlib\axes\_axes.py", line 2528, in broken_barh
    xranges = self.convert_xunits(xranges)
  File "C:\...\lib\site-packages\matplotlib\artist.py", line 186, in convert_xunits
    return ax.xaxis.convert_units(x)
  File "C:\...\lib\site-packages\matplotlib\axis.py", line 1530, in convert_units
    ret = self.converter.convert(x, self.units, self)
  File "C:\...\lib\site-packages\matplotlib\dates.py", line 1801, in convert
    return date2num(value)
  File "C:\...\lib\site-packages\matplotlib\dates.py", line 428, in date2num
    return _to_ordinalf_np_vectorized(d)
  File "C:\...\lib\site-packages\numpy\lib\function_base.py", line 1972, in __call__
    return self._vectorize_call(func=func, args=vargs)
  File "C:\...\lib\site-packages\numpy\lib\function_base.py", line 2048, in _vectorize_call
    outputs = ufunc(*inputs)
  File "C:\...\lib\site-packages\matplotlib\dates.py", line 229, in _to_ordinalf
    base = float(dt.toordinal())
AttributeError: 'datetime.timedelta' object has no attribute 'toordinal'

Expected outcome

A graph showing a single bar from 20:00 to 21:00.

If this is a limitation of the current version of matplotlib, I'd be perfectly happy with a workaround that gave the expected result by another means (but the approaches I've tried have resulted in the axis tick marks not being correctly formatted as times).

Matplotlib version

  • Operating system: Windows 7
  • Matplotlib version: 3.0.2
  • Matplotlib backend (print(matplotlib.get_backend())): TkAgg
  • Python version: 3.7.1
  • Jupyter version (if applicable): N/A
  • Other libraries: None

Python installed from the python.org Windows 64-bit installer. Matplotlib installed from the wheel on PyPI (pipenv install matplotlib).

@jklymak
Copy link
Member

jklymak commented Nov 22, 2018

#12863 should fix this now, after some pain. Its a bit difficult for there to be essentially two "units" in a single list, but its a perfectly valid use case, so...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants