Skip to content

ax.bar throws when x axis is pandas datetime #13186

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
david-waterworth opened this issue Jan 14, 2019 · 8 comments · Fixed by #13187
Closed

ax.bar throws when x axis is pandas datetime #13186

david-waterworth opened this issue Jan 14, 2019 · 8 comments · Fixed by #13187

Comments

@david-waterworth
Copy link

Bug report

Bug summary

ax.bar throws error when x-axis is datetime, behaviour has changed between current master (throws error) and version 3.0.2 (no error)

Code for reproduction

import pandas as pd
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(20,10));
ax = fig.gca();

df = pd.DataFrame({'year':[2018,2018,2018],'month':[1,1,1], 'day':[1,2,3], 'value':[1,2,3]})
df['date'] = pd.to_datetime(df[['year', 'month', 'day']])

ax.bar(df['date'], df['value'], width=10,align='center')

Actual outcome

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-12-500999fd6ea9> in <module>
      8 df['date'] = pd.to_datetime(df[['year', 'month', 'day']])
      9 
---> 10 ax.bar(df['date'], df['value'], width=10,align='center')

~/matplotlib/lib/matplotlib/__init__.py in inner(ax, data, *args, **kwargs)
   1515     def inner(ax, *args, data=None, **kwargs):
   1516         if data is None:
-> 1517             return func(ax, *map(sanitize_sequence, args), **kwargs)
   1518 
   1519         bound = new_sig.bind(ax, *args, **kwargs)

~/matplotlib/lib/matplotlib/axes/_axes.py in bar(self, x, height, width, bottom, align, **kwargs)
   2230             x0 = x
   2231             x = np.asarray(self.convert_xunits(x))
-> 2232             width = self._convert_dx(width, x0, x, self.convert_xunits)
   2233             if xerr is not None:
   2234                 xerr = self._convert_dx(xerr, x0, x, self.convert_xunits)

~/matplotlib/lib/matplotlib/axes/_axes.py in _convert_dx(dx, x0, xconv, convert)
   2055                 dx = [dx]
   2056                 delist = True
-> 2057             dx = [convert(x0 + ddx) - x for ddx in dx]
   2058             if delist:
   2059                 dx = dx[0]

~/matplotlib/lib/matplotlib/axes/_axes.py in <listcomp>(.0)
   2055                 dx = [dx]
   2056                 delist = True
-> 2057             dx = [convert(x0 + ddx) - x for ddx in dx]
   2058             if delist:
   2059                 dx = dx[0]

pandas/_libs/tslibs/timestamps.pyx in pandas._libs.tslibs.timestamps._Timestamp.__add__()

ValueError: Cannot add integral value to Timestamp without freq.

Expected outcome

Matplotlib version
built matplotlib from source

@jklymak
Copy link
Member

jklymak commented Jan 14, 2019

That this worked before seems fortuitous, but not consistent with other dates. What units are 10 supposed to be in this example? I’m not clear on what pandas has for a timedelta, but that’s what we would expect for a date using other Datetimes with bar.

Open to the idea that this behaviour still needs to be changed. I got talked into the current implementation, but maybe it’s wrong.

@jklymak
Copy link
Member

jklymak commented Jan 14, 2019

Crossref #12903

@jklymak
Copy link
Member

jklymak commented Jan 14, 2019

? Are you sure that worked v3.0.2 w/o an error? It fails for me back to v2.2.3 (which is where I quit, because I would have to recompile)

Traceback (most recent call last):
  File "testPandas.py", line 10, in <module>
    ax.bar(df['date'], df['value'], width=10,align='center')
  File "/Users/jklymak/matplotlib/lib/matplotlib/__init__.py", line 1810, in inner
    return func(ax, *args, **kwargs)
  File "/Users/jklymak/matplotlib/lib/matplotlib/axes/_axes.py", line 2277, in bar
    left = x - width / 2
TypeError: ufunc subtract cannot use operands with types dtype('<M8[ns]') and dtype('float64')

@jklymak jklymak added the status: needs clarification Issues that need more information to resolve. label Jan 14, 2019
@david-waterworth
Copy link
Author

david-waterworth commented Jan 15, 2019

@jklymak actually that specific example doesn't work on 3.0.2 - what did work then but fails now is slightly more complicated - I was grouping by my date column. I guess because the tpye of the grouped column is a pandas.core.indexes.datetimes.DatetimeIndex and perhaps that supports addition with a unit-less width?

import pandas as pd
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(20,10));
ax = fig.gca();

df = pd.DataFrame({'year':[2018,2018,2018],'month':[1,2,3], 'day':[1,2,3], 'value':[1,3,2]})
df['date'] = pd.to_datetime(df[['year', 'month', 'day']])
monthly = df[['date','value']].groupby(['date']).sum()

dates = monthly.index
colours = ['lightslategray','lightsteelblue','lightslategray']
forecast = monthly['value']
baseline = monthly['value']
ax.bar(dates, forecast, color = colours, width=10,align='center')
ax.plot(dates, baseline, color = 'orange',lw=4)

@jklymak
Copy link
Member

jklymak commented Jan 15, 2019

Given that the error is ValueError: Cannot add integral value to Timestamp without freq. I think pandas should really change that to a TypeError, but, see #13187 for a quick fix that seems to work.

@jklymak
Copy link
Member

jklymak commented Jan 15, 2019

I suspect you really should be passing something more meaningful in as the width there, but since pandas allows it, we shouldn't break it.

@jklymak jklymak removed the status: needs clarification Issues that need more information to resolve. label Jan 15, 2019
@jklymak jklymak changed the title ax.bar throws when x axis is datetime ax.bar throws when x axis is pandas datetime Jan 15, 2019
@david-waterworth
Copy link
Author

Yeah i agree - it's confusing that it appears to work in one case but not the other. Thanks

@jklymak
Copy link
Member

jklymak commented Jan 15, 2019

Lets leave open until we get our fix in. #13187 will automatically close it...

@QuLogic QuLogic added this to the v3.1 milestone Jan 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants