2

I have a pandas dataframe with timestamps as index and numeric values in the columns. I want to use broken_bar to draw rectangles to highlight some portions of the timeseries. How to use timestamps with broken_barh?

df.plot(ax = ax)
ax.broken_barh([(startTs, pd.offsets.Week())], (10,50), facecolors = colors, alpha = 0.25)
# Where type(startTs) is pandas.tslib.Timestamp

When I execute the above snippet, I get 'argument must be a string or a number' error.

Thanks in advance.

Shravan
  • 2,553
  • 2
  • 16
  • 19

1 Answers1

10

As far I understand, pandas plot timeseries by using period values according to the frequency of your index. This makes sense because matplotlib only understands number as values for the axis and thus your call to broken_barh fails because your are passing a non-number value.

To get the integer value of a period of a timestamp you need to use .to_period(). See:

In [110]: pd.to_datetime('2014-04-02').to_period('D').ordinal
Out[110]: 16162

In [111]: pd.to_datetime('2014-04-02').to_period('W').ordinal
Out[111]: 2310

Then, depending on your timestamps interval (days, weeks, months, etc) you need to figure out what's the width you want to use for the broken bar.

In the example below, the frequency is 1 day and the width of the bar for one week is 7 units.

import numpy as np
import matplotlib.pylab as plt
import pandas as pd

idx = pd.date_range('2013-04-01', '2013-05-18', freq='D')
df = pd.DataFrame({'values': np.random.randn(len(idx))}, index=idx)
ax = df.plot()

start_period = idx[0].to_period('D').ordinal
bar1 = [(start_period, 7), (start_period + 10, 5), (start_period + 25, 4)]
bar2 = [(start_period, 1), (start_period + 22, 3), (start_period + 40, 2)]
ax.broken_barh(bar1, [2, .2], facecolor='red')
ax.broken_barh(bar2, [-2, .2], facecolor='green')
plt.show()

broken bar with timestamps

R. Max
  • 6,624
  • 1
  • 27
  • 34
  • Hi Rolando. Thanks for the answer - it worked for me up until the last pandas update. Now `broken_barh` cause `TypeError: not all arguments converted during string formatting`. Do you perhaps know how to fix it? – Vladimir Aug 30 '16 at 08:21
  • As a workaround meanwhile: dropping ordinals and using `matplotlib.dates.date2num` as suggested here http://stackoverflow.com/a/11056898/3160867 looks to be solving the issue – Vladimir Aug 30 '16 at 08:22