Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly use FuncFormatter(func)?

class matplotlib.ticker.FuncFormatter(func) The function should take in two inputs (tick value x and position pos) and return a string

def millions(x, pos):
    'The two args are the value and tick position'
    return '$%1.1fM' % (x*1e-6)

What happened to the pos parameter? It isn't even set to None.

I added print(pos) and got 0 1 2 3 4, plus a lot of None when I moved my mouse over the image. Only I don't know what to do with that information.

I have seen examples where x is used but not pos, and I don't understand how it is supposed to be used. Can someone give me an example? Thanks

like image 838
JMJ Avatar asked Nov 09 '16 16:11

JMJ


2 Answers

Here is an example provided by Maplotlib documentations.

from matplotlib.ticker import FuncFormatter
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(4)
money = [1.5e5, 2.5e6, 5.5e6, 2.0e7]


def millions(x, pos):
    'The two args are the value and tick position'
    return '$%1.1fM' % (x*1e-6)

formatter = FuncFormatter(millions)

fig, ax = plt.subplots()
ax.yaxis.set_major_formatter(formatter)
plt.bar(x, money)
plt.xticks(x + 0.5, ('Bill', 'Fred', 'Mary', 'Sue'))
plt.show()

which produces

enter image description here

like image 109
SparkAndShine Avatar answered Sep 23 '22 06:09

SparkAndShine


The FuncFormatter gives you a very flexible way to define your own (e.g. dynamic) tick label formatting to an axis.

Your custom function should accept x and pos parameters, where pos is the (positional) number of the tick label that is currently being formatted, and the x is the actual value to be (pretty) printed.

In that respect, the function gets called each time a visible tick mark should be generated - that's why you always get a sequence of function calls with positional argument starting from 1 to the maximal number of visible arguments for your axis (with their corresponding values).

Try running this example, and zoom the plot:

from matplotlib.ticker import FuncFormatter
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(4)
y = x**2


def MyTicks(x, pos):
    'The two args are the value and tick position'
    if pos is not None:
        tick_locs=ax.yaxis.get_majorticklocs()      # Get the list of all tick locations
        str_tl=str(tick_locs).split()[1:-1]         # convert the numbers to list of strings
        p=max(len(i)-i.find('.')-1 for i in str_tl) # calculate the maximum number of non zero digit after "."
        p=max(1,p)                                  # make sure that at least one zero after the "." is displayed
        return "pos:{0}/x:{1:1.{2}f}".format(pos,x,p)

formatter = FuncFormatter(MyTicks)

fig, ax = plt.subplots()
ax.yaxis.set_major_formatter(formatter)
plt.plot(x,y,'--o')
plt.show()

The result should look like this:

Example image

like image 23
Bitstream Avatar answered Sep 22 '22 06:09

Bitstream