pandas-dev / pandas

Flexible and powerful data analysis / manipulation library for Python, providing labeled data structures similar to R data.frame objects, statistical functions, and much more
https://pandas.pydata.org
BSD 3-Clause "New" or "Revised" License
42.75k stars 17.62k forks source link

Using pandas.TimeSeries_DateFormatter in bar plot? #1918

Open sinhrks opened 11 years ago

sinhrks commented 11 years ago

xref #5774

When time series is set as index, line plot uses the TimeSeries_DateFormatter for recognizable date formatting. However, bar plot use the FixedFormatter which outputs the datetime as it is. Can bar plot also use the DateFormatter?

In [1]: from pandas import *
In [2]: from numpy.random import *
In [3]: ts = Series(randn(100), index=date_range('1/1/2000', periods=100))
In [4]: df = DataFrame(randn(100, 4), index=ts.index, columns=['A', 'B', 'C', 'D'])
In [5]: df = df.cumsum()

In [7]: a = df.plot(kind='bar')
In [9]: a.get_xaxis().get_major_formatter()
Out[9]: <matplotlib.ticker.FixedFormatter instance at 0x108700f38>

In [11]: a = df.plot()
In [12]: a.get_xaxis().get_major_formatter()
Out[12]: <pandas.tseries.converter.TimeSeries_DateFormatter instance at 0x10877ccf8>
datapythonista commented 9 years ago

Just in case it's useful, I found a bug that looks related to this issue to me. This code from an ipython notebook shows the problem:

%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib
ts = pd.Series(np.random.randn(100), index=pd.date_range('1/1/2000', periods=100))
ax = ts.plot(kind='bar')
ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%m %d %Y'))

The first time it's executed it shows this warning, and the plot does not show:

~/.pydata/lib/python2.7/site-packages/IPython/core/formatters.py:239: FormatterWarning: Exception in image/png formatter: DateFormatter found a value of x=0, which is an illegal date. This usually occurs because you have not informed the axis that it is plotting dates, eg with ax.xaxis_date() FormatterWarning,

Next executions the warning does not appear, neither the plot.

Some things that makes the plot appear:

Hope this helps

jorisvandenbossche commented 9 years ago

Related with #8803

ehsteve commented 8 years ago

I've just run into this problem as well. Would very much appreciate a fix.

tharibo commented 8 years ago

Same problem here. Is there a workaround?

pwaller commented 8 years ago

Funny, I subscribed to this issue yesterday and someone replies to it! I too have had lots of problems with plot(kind="bar") with time series data. A lot of things are screwed up. The x-axis dates aren't shown correctly, ax.twinx() doesn't work properly. I've resorted to using plt.bar(df.index, df.values) with much greater success.

pwaller commented 7 years ago

Just hit this again. Can't figure out how to get the bar plot to show dates sensibly at all, it's showing a complete timestamp "%d/%m/%Y %H:%M:%S" for something which is a 2-month granularity. I just want it to show 04/2017, but the obvious ax.xaxis.set_major_formatter(plt.DateFormatter('%m/%Y')) does not work.

pwaller commented 7 years ago

Exception for reference:

/home/pwaller/.local/lib/python3.5/site-packages/matplotlib/dates.py in __call__(self, x, pos)
    460     def __call__(self, x, pos=0):
    461         if x == 0:
--> 462             raise ValueError('DateFormatter found a value of x=0, which is '
    463                              'an illegal date.  This usually occurs because '
    464                              'you have not informed the axis that it is '

ValueError: DateFormatter found a value of x=0, which is an illegal date.  This usually occurs because you have not informed the axis that it is plotting dates, e.g., with ax.xaxis_date()
pwaller commented 7 years ago

I found a workaround, by applying this at the end:

In this case, d is the DataFrame I'm plotting, and d.index is the DatetimeIndex.

plt.gca().xaxis.set_major_formatter(plt.FixedFormatter(d.index.to_series().dt.strftime("%b %Y")))
shankari commented 6 years ago

https://github.com/pandas-dev/pandas/issues/1918#issuecomment-297019907 works! Just FYI, if you have stored the axis for the plot already (as in https://github.com/pandas-dev/pandas/issues/1918#issuecomment-65372559), you can also do

ax.xaxis.set_major_formatter(plt.FixedFormatter(ts.index.to_series().dt.strftime("%d %b %Y")))
pwaller commented 6 years ago

I'm not a huge fan of the workaround and hit this quite frequently still. It also doesn't produce x-axis labels which are as good a data.plot() does, because the latter does Year labels on a separate row than Month labels, and I don't know how to achieve the same effect. I'd love for bar chars to be able to display time series data in the same way that line plots do, sometimes it is a less misleading way to present the data.

jfuentescpp commented 5 years ago

workaround still saving the day!

How to set xlim with this solution? Already tried ax.set_xlim([datetime(2018, 6, 1, 0,0), datetime(2019, 3, 1, 0,0)]) ax.set_xlim(pd.Timestamp() ...

poke1024 commented 3 years ago

This is still not working without the workaround in Pandas 1.1.5 :-/

Compro-Prasad commented 4 months ago

xref #5774

When time series is set as index, line plot uses the TimeSeries_DateFormatter for recognizable date formatting. However, bar plot use the FixedFormatter which outputs the datetime as it is. Can bar plot also use the DateFormatter?

In [1]: from pandas import *
In [2]: from numpy.random import *
In [3]: ts = Series(randn(100), index=date_range('1/1/2000', periods=100))
In [4]: df = DataFrame(randn(100, 4), index=ts.index, columns=['A', 'B', 'C', 'D'])
In [5]: df = df.cumsum()

In [7]: a = df.plot(kind='bar')
In [9]: a.get_xaxis().get_major_formatter()
Out[9]: <matplotlib.ticker.FixedFormatter instance at 0x108700f38>

In [11]: a = df.plot()
In [12]: a.get_xaxis().get_major_formatter()
Out[12]: <pandas.tseries.converter.TimeSeries_DateFormatter instance at 0x10877ccf8>

Screenshots for reference: image image

Just in case it's useful, I found a bug that looks related to this issue to me. This code from an ipython notebook shows the problem:

%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib
ts = pd.Series(np.random.randn(100), index=pd.date_range('1/1/2000', periods=100))
ax = ts.plot(kind='bar')
ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%m %d %Y'))

The first time it's executed it shows this warning, and the plot does not show:

~/.pydata/lib/python2.7/site-packages/IPython/core/formatters.py:239: FormatterWarning: Exception in image/png formatter: DateFormatter found a value of x=0, which is an illegal date. This usually occurs because you have not informed the axis that it is plotting dates, eg with ax.xaxis_date() FormatterWarning,

Next executions the warning does not appear, neither the plot.

Some things that makes the plot appear:

* Removing the `kind='bar'`

* Removing the last line of code, where the formatter is set

* Changing the DateFormatter by another like the FormatStrFormatter

* Using `plt.bar` instead of pandas Series `plot` method

Hope this helps

The above mentioned warning doesn't show up anymore: image