I'm trying to set up an inverted axis bar chart such that smaller numbers have bigger bars, and those bars start from the top of the bar chart. Ideally, my y-axis would vary from 10e-10 on the bottom to 10e-2 on the top, and would look similar to this excel plot:

In presenting this data, getting to a lower number is better, so I was hoping to represent this with bigger bars, rather than the absence of bars.
Inverting the y-axis limits makes the bars start from the top, but it does not solve my problem, since the smaller bars are still associated with the smaller numbers. Is there some way to move the origin, and specify that bars should be drawn from the origin to the appropriate tick on the axis?
The data and code are really not so important here, but here is an excerpt:
plt.rcParams['xtick.bottom'] = plt.rcParams['xtick.labelbottom'] = False
plt.rcParams['xtick.top'] = plt.rcParams['xtick.labeltop'] = True
barVals = [ 10**(-x) for x in range(10) ]
ticks = [x for x in range(10)]
plt.bar(ticks, barVals)
plt.yscale('log')
plt.ylim([1e-2, 1e-10])
#plt.axes().spines['bottom'].set_position(('data', 0))
plt.show()

The resultant plot has bigger bars for bigger numbers and smaller bars for smaller numbers. I could instead plot the difference between each value and the maximum, but I was hoping there was some built-in way to do this in matplotlib/pyplot.
Using matlab, the functionality I am looking for is setting the axis base value:
b = bar(ticks, barValues);
b(1).BaseValue = 1e0;
Given the way a normal log-scaling of the axis works, I think your best bet is to scale the data manually, and adjust the labels to match. The following is a simple example to get you started, using the OO API:
data = 10.0**np.arange(-2, -7, -1)
plot_data = np.log10(data)
fig, ax = plt.subplots()
ax.bar(np.arange(data.size) + 1, plot_data)
You can set the ticks manually, but I would recommend using a Formatter:
from matplotlib.ticker import StrMethodFormatter
...
ax.yaxis.set_major_formatter(StrMethodFormatter('$10^{{{x}}}$'))
This particular Formatter accepts a template string suitable for str.format and interpolates it with the tick value bound to the name x. If you only wanted to display the integer portion of the exponent, you could initialize it as
StrMethodFormatter('$10^{{{x:.0f}}}$')
The symbols $...$ tell matplotlib that the string is LaTeX, and {{...}} are escaped curly braces to tell LaTeX to group the entire exponent as a superscript.
To adjust the limits of your chart:
ax.set_ylim([plot_data.min() - 0.5, -1])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With