0

I am trying to plot a double y axis graph having dates on the x-axis using matplotlib

The dates are daily but I would like the x-axis labels to show the dates say every 10 days or so.

This works fine on a single y-axis graph as below:

x = z['date']
y = z['volume']
#plt.bar(x,y, 0.2, color = 'blue')


fig, ax=plt.subplots()
ax = plt.subplot(111)

ax.bar(x,y, width= 0.3)
ax.xaxis.set_major_locator(DayLocator(bymonthday = range(1,32), interval = 
10))
ax.xaxis.set_major_formatter(DateFormatter('%Y-%m-%d'))
plt.xticks(rotation = 45)   

plt.show()

But I can't seem to get them displaying with two y-axis. I am trying the below code currently:

Here is a sample of the Dataframe DV:

DV
Out[291]: 
   volume  price  Date   DayDate
0    9100   6.00  1990  736018.0
1   12796   7.90  1984  736082.0
2   14465   7.56  2007  736088.0
3   15000   7.45  1992  736103.0

# note, the index of the df is actually the same as the date column 

example of entries in one row index 2016-02-24, 9107.4540, 6.00, 2016-02-24, 736018.0

Now the code for plotting double axis graph:

fig, ax=plt.subplots()
ax = plt.subplot(111)

x = DV['Date'] # nb ; DV['Date'] = date2num(pd.to_datetime(DV ['Date']).tolist())
y = DV['Volume']
y1 = DV['price']

ax.bar(x,y, width = 0.8)

ax.xaxis.set_major_locator(DayLocator(bymonthday = range(1,32), interval =  10))
ax.xaxis.set_major_formatter(DateFormatter('%Y-%m-%d'))

ax2 = ax.twinx()
ax2.plot(ax.get_xticks(), DV['price'], marker = 'o', linestyle = '-', color 
= 'r')

ax2.legend(loc='upper right')
ax.legend(loc='upper left')
ax.set_ylabel('Volume ')
ax2.set_ylabel('price')

ax.set_xlabel('Date')

plt.xticks(rotation = 45)
ax.set_title('daily price v. volume')
ax.set_ylim(0,1.3*DV["volume"].max())
ax2.set_ylim(0,1.3*DV["price"].max())

ax2.grid(False)
plt.autoscale()
plt.show()

Any help would be much appreciated!

Izzy888
  • 65
  • 2
  • 10
  • What is your error message? – pjw Oct 17 '17 at 14:44
  • In order to be able to use a matplotlib DayLocator your axis needs to be plotted from within matplotlib. However, in the second code, you use the pandas plotting wrapper. Pandas datetime plots are in general incompatible with matplot datetime plots. If you are in need of a specific formatter or locator, use matplotlib plotting function throughout the code. – ImportanceOfBeingErnest Oct 17 '17 at 15:29
  • In agreement. I usually do analysis and data-wrangling in Pandas, then plot in matplotlib. Either way, you need to stick with just matplotlib or Pandas for your plotting code. Try defining `ax` in your second code as you do in your first code, and see what happens. – pjw Oct 17 '17 at 16:40
  • @PJW Hi, it's not so much that I get an error. When I run the above code for the double axis it just doesn't display any x-axis labels – Izzy888 Oct 18 '17 at 14:05
  • If I change the ax plotting to: ax.bar(x,y, width = 0.8) , then apply formatting of x-axis to ax. In order to plot the 2nd y axis I use: ax2.plot(ax.get_xticks(), y1, marker = 'o', linestyle = '-', color = 'r') --> is the use of '.plot' making in pandas framework and not matplotlib? On making these changes to the plotting I get the error; x and y must have same first dimension, but have shapes (0L,) and (55L,) – Izzy888 Oct 18 '17 at 15:20
  • @Izzy888 `.plot` can be used in matplotlib or Pandas, and which library is being used depends on how you define `ax`. If you use `ax = DV['volume'].plot(kind="bar", alpha=0.7)`, you are applying `.plot` to a Pandas Series, so `ax` is defined within the Pandas plotting wrapper. However, if you use `fig, ax = plt.subplots()`, you are defining `ax` as an axes object in matplotlib. So before you use `.plot` or `.bar`, you need to make sure `ax` and `ax2` are defined as matplotlib objects. Then you can use the Pandas variables within the matplotlib plotting commands, as you do in your first code. – pjw Oct 18 '17 at 20:30
  • @PJW thanks for explaining that so well, I understand what you mean now! I have altered my code in the question to include ax & ax2 defined in matplotlib . my code still doesn't deliver the dates spaced as I would like them and I now have a ValueError: x and y must have same first dimension, but have shapes (25L,) and (55L,) - my plight goes on! – Izzy888 Oct 19 '17 at 09:18
  • Add to your question a print of your dataframe `DV`. – pjw Oct 19 '17 at 15:29
  • @ImportanceOfBeingErnest You may want to re-open this question, as the issue regarding matplotlib/Pandas incompatibility has been resolved, yet the problem remains. I can provide an answer. – pjw Oct 19 '17 at 16:42
  • Yes I can reopen the question once a [mcve] is provided. Any solution will strongly depend on the format of `x`, hence this needs to be given in the question. See [How to make good reproducible pandas examples](https://stackoverflow.com/questions/20109391/how-to-make-good-reproducible-pandas-examples). – ImportanceOfBeingErnest Oct 19 '17 at 18:42
  • Hello, I have given a sample of the rows and formats of fields above ( sorry for the messiness, I wasn't able to copy in neatly). I'm looking at df's with up to 50 dates along the x-axis so spacing by displaying 1 x-axis label every 10 days would help a lot. thanks – Izzy888 Oct 20 '17 at 09:55
  • Yes, having your dataframe indexed with DateTime is key in Pandas. Then you have access to a lot of built-in tools. Make sure all your columns are of equal length -- then, I would recommend plotting an actual Pandas Series (a column of data) as your `x`, rather than `ax.get_xticks()`. Whether you're working on the left or the right y-axis, just plot real data, and then deal with the tick-spacing separately. – pjw Oct 20 '17 at 15:28

0 Answers0