Changing type of annotation in mplcursors on matplotlib

493 Views Asked by At

The current format

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import ScalarFormatter
import mplcursors as mpl

class Compound():
    def accumulation(i,t):
        return (1+i)**t
    def discount(i,t):
        return (1-i)**(-t)
    
years= np.linspace(1,1000,12000)

%matplotlib widget

fig, ax = plt.subplots()
ax.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))

plt.plot(years,0.93*Compound.accumulation(0.0225,years))
plt.title('Interest')

mpl.cursor(hover=True).annotation_kwargs

I'm using a Jupiter notebook and I want to change the scientific format in the annotation that mplcursors creates when the cursor hovers above the lines

1

There are 1 best solutions below

1
Matt Pitkin On BEST ANSWER

The mplcursors package uses the matplotlib Axes.format_coord to set the style of the formatters in the annotation box. So, you can define your own format_coord function and use that instead (see, e.g., here).

For example,

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import ScalarFormatter
import mplcursors as mpl


class Compound():
    def accumulation(i, t):
        return (1 + i)**t
    def discount(i, t):
        return (1 - i)**(-t)
    
years = np.linspace(1, 1000, 12000)


def format_coord(x, y):
    # output numbers (not in scientific notation) with one decimal place
    return f"x={x:.1f}, y={y:.1f}"


fig, ax = plt.subplots()
ax.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))

ax.plot(years, 0.93 * Compound.accumulation(0.0225, years))
ax.set_title("Interest")

# switch axes format_coord function to your own 
ax.format_coord = format_coord

mpl.cursor(hover=True)

plt.show()

Unfortunately, this doesn't seem to work with LaTeX/MathText style strings enclosed in $ signs, e.g., using:

def format_coord(x, y):
    yscale = int(np.log10(y))
    
    # return LaTeX style scientific notation
    return rf"x={x:1.1f}, y=${y / 10**yscale:1.1f} \times 10^{yscale}$"

keeps the dollars and does not render it as an equation. Doing that may required a more in-depth hack.