A multi-axis plot with a line on top. Matplotlib

I am trying to use doublex () to create a combined bar / line graph with a line visible on top of the line. It currently looks like this:

Bar / Line Combo

I also want a line chart to be plotted on the left vertical axis (ax), and the right (ax2) at the moment. If I draw a line on the second axis it appears on top, but obviously it appears on the wrong axis (right)

Here's my code:

    self.ax2=ax.twinx()
    df[['Opportunities']].plot(kind='bar', stacked=False, title=get_title, color='grey', ax=self.ax2, grid=False)
    ax.plot(ax.get_xticks(),df[['Percentage']].values, linestyle='-', marker='o', color='k', linewidth=1.0)
    lines, labels = ax.get_legend_handles_labels()
    lines2, labels2 = self.ax2.get_legend_handles_labels()
    ax.legend(lines + lines2, labels + labels2, loc='lower right')

      

There are also problems with labels, but only one thing at a time.

+3


source to share


1 answer


By default, by default, artists are drawn on ax

, then artists on double axes ax2

from above. Since in your code the line graph was drawn on ax

and the hatch graph on ax2

, the stroke graph sits on top of (and hides) the line.

(I thought I could change this by pointing out zorder

, but this attempt doesn't work ...)

Thus, one way to solve the problem is to use a ax

stroke to draw a graph and ax2

to draw a line. This will place the line on top of the bars. It will also, by default, place yticks for ax

(stroke plot) on the left and yticks for ax2

(string) on ​​the right. However, you can use

ax.yaxis.set_ticks_position("right")
ax2.yaxis.set_ticks_position("left")

      

to swap the labels on the left and right.


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import pandas as pd
np.random.seed(2015)

N = 16
df = pd.DataFrame({'Opportunities': np.random.randint(0, 30, size=N),
                   'Percentage': np.random.randint(0, 100, size=N)},
                  index=pd.date_range('2015-3-15', periods=N, freq='B').date)
fig, ax = plt.subplots()

df[['Opportunities']].plot(kind='bar', stacked=False, title='get_title', 
                           color='grey', ax=ax, grid=False)
ax2 = ax.twinx()
ax2.plot(ax.get_xticks(), df[['Percentage']].values, linestyle='-', marker='o', 
        color='k', linewidth=1.0, label='percentage')

lines, labels = ax.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax.legend(lines + lines2, labels + labels2, loc='best')
ax.yaxis.set_ticks_position("right")
ax2.yaxis.set_ticks_position("left")

fig.autofmt_xdate()
plt.show()

      

gives



enter image description here


Alternatively, the axes zorder

for the axes can be set to draw ax

above ax2

. Paul Ivanov shows how :

ax.set_zorder(ax2.get_zorder()+1) # put ax in front of ax2
ax.patch.set_visible(False) # hide the 'canvas'
ax2.patch.set_visible(True) # show the 'canvas'

      

Thus,

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import pandas as pd
np.random.seed(2015)

N = 16
df = pd.DataFrame({'Opportunities': np.random.randint(0, 30, size=N),
               'Percentage': np.random.randint(0, 100, size=N)},
index=pd.date_range('2015-3-15', periods=N, freq='B').date)
fig, ax = plt.subplots()
ax2 = ax.twinx()
df[['Opportunities']].plot(kind='bar', stacked=False, title='get_title', 
                           color='grey', ax=ax2, grid=False)

ax.plot(ax.get_xticks(), df[['Percentage']].values, linestyle='-', marker='o', 
        color='k', linewidth=1.0, label='percentage')

lines, labels = ax.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax.legend(lines + lines2, labels + labels2, loc='best')

ax.set_zorder(ax2.get_zorder()+1) # put ax in front of ax2
ax.patch.set_visible(False) # hide the 'canvas'
ax2.patch.set_visible(True) # show the 'canvas'

fig.autofmt_xdate()
plt.show()

      

gives the same result without having to change the roles played by ax

and ax2

.

+3


source







All Articles