How do I invert matplotlib bars at a specific point instead of when negative?

Viewed 48

I'd like to invert the bars in this diagram when they are below 1, not when they are negative. Additionally I'd like to have even spacing between the ticks/steps on the y-axis

Here is my current code

import matplotlib.pyplot as plt
import numpy as np

labels = ['A','B','C']

Vals1 = [28.3232, 12.232, 9.6132]
Vals2 = [0.00456, 17.868, 13.453]
Vals3 = [0.0032, 1.234, 0.08214]

x = np.arange(len(labels)) 
width = 0.2 
fig, ax = plt.subplots()
rects1 = ax.bar(x - width, Vals1, width, label='V1')
rects2 = ax.bar(x, Vals2, width, label='V2')
rects3 = ax.bar(x + width, Vals3, width, label='V3')

ax.set_xticks(x)
ax.set_xticklabels(labels) 
plt.xticks(rotation=90)
ax.legend()
yScale = [0.0019531,0.0039063,0.0078125,0.015625,0.03125,0.0625,0.125,0.25,0.5,1,2,4,8,16,32]
ax.set_yticks(yScale)
plt.show()

enter image description here

I believe I've stumbled upon the answer, here it is for anyone else looking for the solution. Add the argument bottom='1' to ax.bar instantiation, and then flip the values in the array.

for i in range(len(Vals1)):
    Vals1[i] = (1 - Vals1[i]) * -1
1 Answers

As you mentioned, the key is the bottom param of Axes.bar:

bottom (default: 0): The y coordinate(s) of the bars bases.

But beyond that, you can simplify your plotting code using pandas:

  1. Put your data into a DataFrame:

    import pandas as pd
    df = pd.DataFrame({'V1': Vals1, 'V2': Vals2, 'V3': Vals3}, index=labels)
    
    #         V1        V2       V3
    # A  28.3232   0.00456  0.00320
    # B  12.2320  17.86800  1.23400
    # C   9.6132  13.45300  0.08214
    
  2. Then use DataFrame.sub to subtract the offset and DataFrame.plot.bar with the bottom param:

    bottom = 1
    ax = df.sub(bottom).plot.bar(bottom=bottom)
    
    pandas bar plot with bottom setting
Related