0

I have a bar graph that is log scaled that I am trying to change the y ticks from 10^1, 10^2, etc., to whole numbers. I have tried setting the tick values manually, and tried setting the values from the data, and also setting the format to scalar. One thing I notice in all of the questions I am looking at is that my construction of the graph doesn't include subplot.

def confirmed_cases():
    x = df['Date']
    y = df['Confirmed']
    plt.figure(figsize=(20, 10))
    plt.bar(x, y)
    plt.yscale('log')
#     plt.yticks([0, 100000, 250000, 500000, 750000, 1000000, 1250000])
#     plt.get_yaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
    plt.title('US Corona Cases By Date')
    plt.xlabel('Date')
    plt.ylabel('Confirmed Cases')
    plt.xticks(rotation=90)

enter image description here

6
  • You may have to incorporate the .gca() call - try plt.gca().yscale('log') Commented Apr 27, 2020 at 0:03
  • Do I need to import gca? I get this 'AxesSubplot' object has no attribute 'yscale' which suggests I should change the structure of the function, correct? Commented Apr 27, 2020 at 0:26
  • Apologies, I may not be reading the documentation correctly. There's a call .set_yscale('log) that is specific to axes, and I don't think you need to call gca for that matplotlib.org/3.1.1/api/_as_gen/… What happens if you try plt.set_yscale('log') Commented Apr 27, 2020 at 0:32
  • module 'matplotlib.pyplot' has no attribute 'set_yscale' Commented Apr 27, 2020 at 0:36
  • Perhaps try and follow the answer presented in this question - stackoverflow.com/questions/31193976/… In your original post you mentioned that other questions were relating to subplots; matplotlib has a lot of different ways you can set up axes and subplots, making it a bit difficult to know which way is the best. One side effect of that is that you may need to redo how the plot is set up and follow the subsequent rules/functions of that particular method. Anyway, have a read of that and see if it answers your question Commented Apr 27, 2020 at 1:11

1 Answer 1

2

There a few issues:

  • The formatter needs to be placed at the yaxis of the ax. Useplt.gca() to get the current ax. Note that there is no function plt.get_yaxis().
  • The scalar formatter starts using exponential notation for large numbers. To prevent that, set_powerlimits((m,n)) makes sure the powers are only shown for values outside the range 10**m and 10**n.
  • In a log scale, major ticks are used for values 10**n for integer n. The other ticks or minor ticks, at positions k*10**n for k from 2 to 9. If there are only a few major ticks visible, the minor ticks can also get a tick label. To suppress both the minor tick marks and their optional labels, a NullFormatter can be used.
  • Avoid using a tick at zero for a log-scale axis. Log(0) is minus infinity.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib

plt.figure(figsize=(20, 10))
plt.bar(np.arange(100), np.random.geometric(1/500000, 100))
plt.yscale('log')
formatter = matplotlib.ticker.ScalarFormatter()
formatter.set_powerlimits((-6,9))
plt.gca().yaxis.set_major_formatter(formatter)
plt.gca().yaxis.set_minor_locator(matplotlib.ticker.NullLocator())
plt.yticks([100000, 250000, 500000, 750000, 1000000, 1250000])
plt.show()

resulting plot

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.