0

I am on Python 3.9 and matplotlib 3.7 working in a jupyter-notebook on macos.

I have a range of x values from 0 to 500 000. When turning on scientific notation, it uses the 10^5 as the order of magnitude. I want it to display as multiples of 10^3

Here's some sample code:

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 5e5, 10e3)
y = np.random.random_sample(len(x))

mm = 1 / 25.4

f, ax = plt.subplots(figsize=(210 * mm, 148 * mm), dpi=600)

ax.plot(x, y)
ax.ticklabel_format(axis='x', style='sci', scilimits=(0,0),useMathText=True, useOffset=False)

Which produces this figure: x ticks as multiples of 10^5

I would like 5 x 10^5 to be displayed as 500 x 10^3, e.g.

I tried to create a mpl.ticker.ScalarFormatter object with the arguments inside the ticklabel_formatter function, but when feeding it the object, I get a positional error because it expects 2 arguments.

I have attempted to set the powerlimits attribute to 3 as well as the orderOfMagnitude attribute to 3, but the ScalarFunction rejects those keyword arguments.

I looked at this post here but the xaxis.set_major_formatter does not accept my formatter object.

Parker
  • 3
  • 1
  • 1
    Scientific notation with the power always being a multiple of 3 is referred to as *engineering notation*. Matplotlib comes with an `EngFormatter` class for doing exactly that. – jasonharper Mar 18 '23 at 18:31
  • @jasonharper I accepted the below answer b/c it solved what I was asking for, but wanted to let you know EngFormatter was the solution I didn't know I needed. Thanks for mentioning it. – Parker Mar 20 '23 at 02:36

1 Answers1

1

You need to use matplotlib.ticker module to achieve this.

So the implementation would look like this:

import numpy as np
import matplotlib.pyplot as plt

import matplotlib.ticker as ticker

x = np.arange(0, 5_00000, 10_000)
y = np.random.random_sample(len(x))

mm = 1 / 25.4

f, ax = plt.subplots(figsize=(210 * mm, 148 * mm), dpi=600)

# Define a custom tick label formatting function
def format_tick_label(x, pos):
    return f"{x/1000:.0f}e3"

# Set the x-axis tick labels to multiples of e3
ax.xaxis.set_major_formatter(ticker.FuncFormatter(format_tick_label))



ax.plot(x, y)

The result then looks like this:

enter image description here

it is not easy to find, so here is a link to the docs:

https://matplotlib.org/stable/api/ticker_api.html

D.L
  • 4,339
  • 5
  • 22
  • 45
  • Thanks so much. Agreed that the ticker module documentation is obscure. Yay for StackOverflow's existence. – Parker Mar 20 '23 at 02:36