0

I have a report that I'm trying to add several subplots to. Using this example, I was able to create a combined line/bar fig How to align the bar and line in matplotlib two y-axes chart?

However, I now need to add this as a subplot to an existing plot (if that makes sense). Everything is working for me in terms of formatting, but for some reason I'm not able to show both the line and the bar, only 1 at a time. This is the code I've configured, can someone please let me know what I'm doing wrong?

import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8.5,11))
ax2 = plt.subplot2grid((4, 2), (0, 1))

def billions(x, pos):
    'The two args are the value and tick position'
    return '$%1.1fB' % (x*1e-9)

def millions(x, pos):
    'The two args are the value and tick position'
    return '$%1.1fM' % (x*1e-6)

formatterb = plt.FuncFormatter(billions)
formatterm = plt.FuncFormatter(millions)

barax = ax2.twinx()

data = growthtable[['date','total','profit']]

barax.set_ylabel('Total')
ax2.set_ylabel('Profit')

barax.xaxis.tick_top()
barax.yaxis.set_major_formatter(formatterm)
ax2.yaxis.set_major_formatter(formatterb)
barax.set_title('Revenue and Profits')

data['Revenue'].plot(kind='bar',ax=ax2,facecolor='blue')
data['Profit'].plot(ax=ax2)

Seems very simple/standard, but for some reason depending on the order I place the last 2 lines I either get to see profit or revenue, not both.

enter image description here

enter image description here

Updating the code I get this:

ax2 = plt.subplot2grid((4, 2), (0, 1))

def billions(x, pos):
    'The two args are the value and tick position'
    return '$%1.1fB' % (x*1e-9)

def millions(x, pos):
    'The two args are the value and tick position'
    return '$%1.1fM' % (x*1e-6)

formatterb = FuncFormatter(billions)
formatterm = FuncFormatter(millions)


barax = ax2.twinx()





barax.plot(data.index, data['Profit'], linewidth=3, color='#a64dff')


barax.xaxis.tick_top()
barax.yaxis.set_major_formatter(formatterm)
ax2.yaxis.set_major_formatter(formatterb)

ax2.bar(data.index, data['Revenue'], color='blue')

enter image description here

However as you can see I'm trying to change bar size and color, but that isn't working?

Dick Thompson
  • 599
  • 1
  • 12
  • 26

1 Answers1

0

I would approach this slightly differently. Usually I define my subplots ahead of time which makes them easier to reference.

fig, (ax1, ax1) = plt.subplots(2, sharex=True)

df.profit.plot(ax=ax1)
df.revenue.plot(kind='bar', ax=ax2)

The formatting you can do the same way, just make sure to reference the proper AxesSubplot.

EDIT (Per @DickThompsons comments)

If you want to overlay the two graphs onto a single graph you need to use the AxesSubplot returned by twin for plotting.

In your example you use ax2 for both:

data['Revenue'].plot(kind='bar',ax=ax2,facecolor='blue')
data['Profit'].plot(ax=ax2)

You should use ax2 for one and barax for the other:

data['Revenue'].plot(kind='bar',ax=barax, facecolor='blue')
data['Profit'].plot(ax=ax2)

All else equal that should create the graph you described and place it in the top right corner of the figure. Here is an example I created.

fig = plt.figure()
ax = plt.subplot2grid((4,2), (0,1))
ax2 = ax.twinx()
df.Profit.plot(ax=ax)
df.Revenue.plot(kind='bar', ax=ax2)
ax.yaxis.set_major_formatter(formatterm)
ax2.yaxis.set_major_formatter(formatterb)
fig.show()

enter image description here

Grr
  • 15,553
  • 7
  • 65
  • 85
  • do you see how I'm defining ax2? `ax2 = plt.subplot2grid((4, 2), (0, 1))` I am trying to keep them in the top right subplot, so how would I do that while incorporating gridspec? I don't think I can use that if that makes sense – Dick Thompson Dec 21 '17 at 18:23
  • I'm not sure I follow. Are you trying to place these two sublpots within another subplot at index 0,1 in a 4x2 grid? – Grr Dec 21 '17 at 18:26
  • Similar to this example, https://stackoverflow.com/questions/19952290/how-to-align-the-bar-and-line-in-matplotlib-two-y-axes-chart, I'm trying to make a combined bar/line chart. I just want to put it in the subplot index 0,1 on a 4x2 grid- like you said. So how could I incorporate that first line within my code? That's where I'm confused – Dick Thompson Dec 21 '17 at 18:28
  • @DickThompson I updated the answer to reflect your comments. Is that what you meant? – Grr Dec 21 '17 at 18:39
  • so for the first example you suggested for the edit is what I already have- and it gives me the same issue where it shows one or the other. I tried modifying my code to your example, but I still got the same issue. For some reason it shows up if I'm plotting 2 lines, but if I try a bar and a line only one of them show up – Dick Thompson Dec 21 '17 at 18:56
  • Can you post the updated code? Your question shows you using the same `AxesSubplot` for each call to `df.plot` – Grr Dec 21 '17 at 19:01
  • I tried setting ax=ax2 and ax=barax for all of them and each combo, didn't work. I got it to somehow work, but formatting is still off I will update the question – Dick Thompson Dec 21 '17 at 19:03
  • Hi, I posted the updated code. Am I maybe configuring matplotlib wrong? Because when I copy paste your exact code I get the same exact issue where the bars show up but not the line – Dick Thompson Dec 22 '17 at 18:42