Home > Back-end >  How to add additional arguments to make matplotlib FuncFormatter() more flexible
How to add additional arguments to make matplotlib FuncFormatter() more flexible

Time:07-20

Simple Example

How can I get the '$' symbol on y-ticks (see red circle), but the '£' symbol on x-ticks?

Here's my code so far:

import numpy as np
import matplotlib
from   matplotlib import pyplot as plt

x = np.arange(0,200, 10) # GBP (0, 10, ... 190, 200)
y = x * 1.25             # USD

# Make figure
fig, ax = plt.subplots(1, 1)
ax.scatter(x, y)
ax.set_xlabel('GBP')
ax.set_ylabel('USD')

# How to format tick labels
def format_currency(value, pos):  
    currency = '£'                   # <- hard-coded (for now) - but how to include as argument?
    return f'{currency}{value:.0f}'  # <- e.g., "$100" or "£100"

# Format tick labels
ax.xaxis.set_major_formatter(plt.FuncFormatter(format_currency))
ax.yaxis.set_major_formatter(plt.FuncFormatter(format_currency)) # <- how to add '$' as an argument?

USD vs. GBP with wrong y-tick labels


What I'm aiming for?

Ideally, I'd like to pass the currency symbol as an argument into the format_currency() function. That way, it gives me the flexibility to add a '$' symbol onto the y-tick labels, i.e.:

def format_currency(value, pos, currency):
    return f'{currency}{value:.0f}'

But then (even assuming that can be done), how would the following line change?

ax.yaxis.set_major_formatter(plt.FuncFormatter(format_currency))

What I've considered so far

  • Sure, I could make tailored functions, e.g., format_USD(), format_EUR(), etc., but that's not scalable with so many currencies.
  • I've been toying around with *args but I can't find a way of making it work.

CodePudding user response:

A lambda function can help here:

# Format tick labels
ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda value, pos: f'£{value:.0f}'))
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda value, pos: f'${value:.0f}'))

Taking a step further:

currency_lookup = {'GBP':'£', 'USD':'$'}

cx = currency_lookup['GBP']
cy = currency_lookup['USD']

# Format tick labels
ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda value, pos: f'{cx}{value:.0f}'))
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda value, pos: f'{cy}{value:.0f}'))

While lambda functions are a nice way to do this you can also use named functions like:

def format_currency_x(value, pos):
    return f'{cx}{value:.0f}'
def format_currency_y(value, pos):
    return f'{cy}{value:.0f}'

The cx and cy are from the namespace from which the functions are called.

  • Related