Unable to plot on the secondary y-axis after using invert_xaxis() using Matplotlib

I am trying to have a scatter chart and a bar chart on the same plot.

I am able to draw them both but I am unable to position the charts properly.

Here is the code that I will create the scatter plot

import pandas as pd
import matplotlib.pyplot as plt

rawdata = {'levels' : [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100],
'series1': [0, 0, 0, 0, 0, 0, 0, 0, 0.543, 0.894, 1.673, 1.943, 2.2345, 2.893, 3.578, 4.875, 5.432, 6.904, 7.8903, 8.940, 10.423],
'series2': [0, 0, 0, 0, 0, 0, 0, 0, 0.435, 0.784, 1.563, 1.934, 2.1345, 2.645, 3.456, 4.653, 5.324, 6.435, 7.5432, 8.843, 10.432],
'bar1': [0.32, 0.32, 0.453, 0.5342, 0.5432, 0.32, 0.54, 0.534, 1.9423, 0.43, 0.543, 0.32, 0.42, 0.8, 0.73, 0.54, 0.73, 0.534, 0.532, 0.8, 0.6],
'bar2': [0.00, 1.00, 0.00, 0.00, 1.00, 0.00, 1.00, 1.00, 0.00, 1.00, 1.00, 0.00, 0.00, 0.00, 0.00, 1.00, 1.00, 0.00, 0.00, 0.00, 1.00]}
data = pd.DataFrame(data=rawdata)
fig, ax1 = plt.subplots(figsize=(10,6))
ax1.scatter(data["series1"], data["levels"], s=10, c='r') 
ax1.plot(data['series1'], data['levels'], linewidth=1, c='r')
ax1.scatter(data['series2'], data['levels'], s=10,c='b')
ax1.plot (data["series2"], data['levels'], linewidth=1, c='b')
plt.show()

scatter plot

Now I want to add some horizontal bar charts to the other axis and I did them adding the code,

ax2 = ax1.twinx()
ax2.barh(data['levels'], data['bar1'])

scatter plot with bars

but I want the bars on the other Yaxis.

So tried to use the invert_xaxis() option

ax2.invert_xaxis()

inverted x axis

But even the scatter plot gets inverted. Is there a way to just invert the bar chart? so that it is against the second y axis.

>Solution :

You can set the position of the left side of barh (see doc). From there, set it to the greatest xtick and plot -data['bar1'] instead of data['bar1'].

Note that you can plot line and markers in a single command:

import requests
import pandas as pd
import matplotlib.pyplot as plt

rawdata = {'levels' : [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100],
  'series1': [0, 0, 0, 0, 0, 0, 0, 0, 0.543, 0.894, 1.673, 1.943, 2.2345, 2.893, 3.578, 4.875, 5.432, 6.904, 7.8903, 8.940, 10.423],
  'series2': [0, 0, 0, 0, 0, 0, 0, 0, 0.435, 0.784, 1.563, 1.934, 2.1345, 2.645, 3.456, 4.653, 5.324, 6.435, 7.5432, 8.843, 10.432],
  'bar1': [0.32, 0.32, 0.453, 0.5342, 0.5432, 0.32, 0.54, 0.534, 1.9423, 0.43, 0.543, 0.32, 0.42, 0.8, 0.73, 0.54, 0.73, 0.534, 0.532, 0.8, 0.6],
  'bar2': [0.00, 1.00, 0.00, 0.00, 1.00, 0.00, 1.00, 1.00, 0.00, 1.00, 1.00, 0.00, 0.00, 0.00, 0.00, 1.00, 1.00, 0.00, 0.00, 0.00, 1.00]
}

data = pd.DataFrame(data=rawdata)

fig, ax1 = plt.subplots(figsize=(10,6))
ax1.plot(data['series1'], data['levels'], linewidth=1, c='r', marker='o', markersize=3)
ax1.plot(data["series2"], data['levels'], linewidth=1, c='b', marker='o', markersize=3)

ax2 = ax1.twinx()
ax2.barh(data['levels'], -data['bar1'], left=ax2.get_xlim()[1])

plt.show()

Output:

enter image description here

Leave a Reply