0

I want to plot 2 bars side by side each other but i keep getting an error:

ValueError: Cannot shift with no freq

This error occurred when i set my x in the axes.bar to be x-width.

Here is my code:

df.date_1 = pd.to_datetime(df.date_1)
df_percent.date_1 = pd.to_datetime(df_percent.date_1)

df = df.set_index(df['date_1']).sort_index() 
df_percent = df_percent.set_index(['date_1']).sort_index()
df_percent = df_percent.reindex(df.index).fillna(0)

fig, ax = plt.subplots(figsize=(10, 8))
ax.plot( df.index, df.line1,label='line1', c='b')
ax.plot( df.index, df.line2,label='line2', c='r')

ax2=ax.twinx()

#i added the x-10 to the bar chart that i want to shift to the right
ax2.bar(df_percent.index, df_after, width=10, alpha=0.1, color='r', label='after')
ax2.bar(df_percent.index-10, df_before, width=10, alpha=0.1, color='g', label='before')

If i do a stacked bar chart it works fine.


           date_1                       line1                         line2
date_1                                                              
2014-06-01 2014-06-01                        65                       66
2014-07-01 2014-07-01                        68                       70
2014-08-01 2014-08-01                        62                       65
2014-09-01 2014-09-01                        62                       76
2014-10-01 2014-10-01                        63                       66
2014-11-01 2014-11-01                        79                       80
2014-12-01 2014-12-01                        80                       50
2015-02-01 2015-02-01                        70                       72
2015-03-01 2015-03-01                        67                       67
2015-04-01 2015-04-01                        69                       60
2015-05-01 2015-05-01                        66                       83
           date_1                     before                after
date_1                                                      
2014-06-01 2014-06-01                 19.80                15.37
2014-07-01 2014-07-01                 62.82                44.87
2014-08-01 2014-08-01                 36.70                27.52
2014-09-01 2014-09-01                 56.18                34.27
2014-10-01 2014-10-01                 16.31                10.95
2014-11-01 2014-11-01                 32.35                14.71
2014-12-01 2014-12-01                 53.33                26.67
2015-02-01 2015-02-01                 44.44                17.78
2015-03-01 2015-03-01                 23.08                23.08
2015-04-01 2015-04-01                 36.84                15.79
2015-05-01 2015-05-01                 46.58                13.70
jxn
  • 7,685
  • 28
  • 90
  • 172
  • Which version of matplotlib are you running? Also, consider making a [small, self-contained example](https://stackoverflow.com/help/mcve) that does not require pandas (you could easily use a standard python list): I created an 8 lines of code long variant on your script that basically does the same, but am getting no error. – Oliver W. Jul 14 '15 at 23:56
  • im on 1.4.3 I do hope to find a way to solve this first on pandas since ive invested quite a bit of pandas code on top of this into this script already – jxn Jul 15 '15 at 00:00
  • can you upload your sample data file? – Jianxun Li Jul 15 '15 at 00:01
  • I'm not saying you should do it without pandas in your final version, but for determining what's going wrong you *should* first check whether you have problems getting your plotting code to work for a simpler case. If you don't like that, at least consider adding the relevant dataframes to your question so that those who are looking at your question can simply copy-paste your code to get a head-start. – Oliver W. Jul 15 '15 at 00:04

1 Answers1

0

I think the error message (interpreted as time index cannot shift with an integer with no time frequency attached) complains about the last line of your code df_percent.index-10. It tries to tell pandas to subtract an integer 10 from pd.DatetimeIndex, which is not defined.

By -10, you means shifting the datetime index by 10 days? (use df_percent.index - pd.tseries.offsets.DateOffset(10, 'day') if this is what you want) or simply get index by excluding the first 10 days? (use df_percent.index[10:])

For pandas to plot bars side-by-side:

import pandas as pd
import matplotlib.pyplot as plt

# your data
# =========================================

print(df)

                date_1  line1  line2
date_1                              
2014-06-01  2014-06-01     65     66
2014-07-01  2014-07-01     68     70
2014-08-01  2014-08-01     62     65
2014-09-01  2014-09-01     62     76
2014-10-01  2014-10-01     63     66
2014-11-01  2014-11-01     79     80
2014-12-01  2014-12-01     80     50
2015-02-01  2015-02-01     70     72
2015-03-01  2015-03-01     67     67
2015-04-01  2015-04-01     69     60
2015-05-01  2015-05-01     66     83


print(df_percent)

                date_1  before  after
date_1                               
2014-06-01  2014-06-01   19.80  15.37
2014-07-01  2014-07-01   62.82  44.87
2014-08-01  2014-08-01   36.70  27.52
2014-09-01  2014-09-01   56.18  34.27
2014-10-01  2014-10-01   16.31  10.95
2014-11-01  2014-11-01   32.35  14.71
2014-12-01  2014-12-01   53.33  26.67
2015-02-01  2015-02-01   44.44  17.78
2015-03-01  2015-03-01   23.08  23.08
2015-04-01  2015-04-01   36.84  15.79
2015-05-01  2015-05-01   46.58  13.70

# plot
# ========================================
fig, ax = plt.subplots(figsize=(14, 8))
df[['line1', 'line2']].plot(ax=ax, color=['b', 'r'])
ax2 = ax.twinx()
df_percent[['before', 'after']].plot(kind='bar', ax=ax2, color=['r', 'g'], alpha=0.1)

enter image description here

Jianxun Li
  • 24,004
  • 10
  • 58
  • 76
  • well i really just want to have 2 bar charts next to each other. they both have the same x axis dates – jxn Jul 15 '15 at 00:13
  • @jxn so why you do the subtraction? – Jianxun Li Jul 15 '15 at 00:14
  • want the other bar to be on the right, following this example here: http://stackoverflow.com/questions/14270391/python-matplotlib-multiple-bars – jxn Jul 15 '15 at 00:14
  • @jxn in that example, the axis is the datenum, so integer works fine. try `df_percent.index - pd.tseries.offsets.DateOffset(10, 'day')` for your case. – Jianxun Li Jul 15 '15 at 00:16
  • @jxn by the way, I don't think you need to do this in order to product that bar chart. pandas is smart enough to align two bars side-by-side. Can you upload you sample data so that I can write an example to show you how to do it? – Jianxun Li Jul 15 '15 at 00:17
  • ive updated my post with my data. It looks weird with 2 date columns because it is a print out of the dataframes after indexing and re-indexing. – jxn Jul 15 '15 at 00:31
  • @jxn I've updated my answer. Let me know if this is what you want. :-) – Jianxun Li Jul 15 '15 at 07:28
  • @jxn if you insist of using that way, then you need to first convert datetime to integer number, calculate the bar width manually, and then do two bar plot. I think pandas provides us a short-cut of doing this, why you don't like it? :-) – Jianxun Li Jul 15 '15 at 18:21
  • for some reason my line charts are not showing up and my date axis have timestamp after the date now..was i suppose to delete my earlier code where i converted to datetime and remove the indexing code as well? – jxn Jul 15 '15 at 18:47
  • i had to remove the pd.to_datetime() in order for it the line charts to show up and make the date axis look better. Only thing now is i need to figure how to add labels instead of using col names as the legends – jxn Jul 15 '15 at 19:00
  • @ Jianxuan Li Also, i want to show that date 2015-01-01 may be empty but prefer to show a blank space than totally removing the date from the x-axis – jxn Jul 15 '15 at 20:29
  • @jxn that's the problem of data. Why not just `reindex` your dataframe to have obs every month and fill `NaN` by 0? – Jianxun Li Jul 15 '15 at 21:25