How to control scientific notation in matplotlib?

Question:

This is my data frame I’m trying to plot:

my_dic = {'stats': {'apr': 23083904, 'may': 16786816, 'june': 26197936}}
my_df = pd.DataFrame(my_dic)

This is how I plot it:

ax = my_df['stats'].plot(kind='bar',  legend=False)
ax.set_xlabel("Month", fontsize=12)
ax.set_ylabel("Stats", fontsize=12)
ax.ticklabel_format(useOffset=False) #AttributeError: This method only works with the ScalarFormatter.
plt.show()

The plot:

enter image description here

I’d like to control the scientific notation. I tried to suppress it by this line as was suggested in other questions plt.ticklabel_format(useOffset=False) but I get this error back –

AttributeError: This method only works with the ScalarFormatter

Ideally, I’d like to show my data in (mln).

Asked By: aviss

||

Answers:

Since you already using pandas

import matplotlib.pyplot as plt
my_df.plot(kind='bar')
plt.ticklabel_format(style='plain', axis='y')

enter image description here

Answered By: BENY

Adding this line helps to get numbers in a plain format but with ‘,’ which looks much nicer:

ax.get_yaxis().set_major_formatter(
    matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))

enter image description here

And then I can use int(x)/ to convert to million or thousand as I wish:

enter image description here

Answered By: aviss

If you’re here wondering why you got the error,

AttributeError: This method only works with the ScalarFormatter

then you got the error because as the error says, ticklabel_format only works with ScalarFormatter (which formats tick values as numbers), but some tick labels of your plot are not numbers. For example, in the OP, x-axis tick labels are not numbers so the error was raised (by default both axes are flagged). As what actually was desired was to format the y-axis tick labels, specifying so with axis='y' in ticklabel_format solves the error.

ax = my_df['stats'].plot(kind='bar', legend=False, xlabel='Month', ylabel='Stats', rot=0)
ax.ticklabel_format(axis='y', scilimits=(0,10))   # <--- no error
ax.ticklabel_format(axis='x', scilimits=(0,10))   # <--- error because ticklabels are strings

Also if the y-ticklabels need a thousands separator comma, then set_yticks() could be used to change it as such.

ax = my_df['stats'].plot(kind='bar', legend=False, xlabel='Month', ylabel='Stats', rot=0)
ax.set_yticks(ax.get_yticks()[:-1], [f"{int(x):,}" for x in ax.get_yticks()[:-1]]);

res

Answered By: cottontail