Matplotlib中ticker formatter.limits配合次坐标轴的小数位数调整问题
To force your secondary axis to display a fixed number of decimal places in scientific notation (while retaining Matplotlib's mathtext formatting), you have two reliable approaches:
Approach 1: Use ScalarFormatter for Significant Figures
If you want to control the number of significant digits (aligning with Matplotlib's default behavior but enforcing consistency), use ScalarFormatter with mathtext enabled:
- Import the
tickermodule from Matplotlib. - Create a
ScalarFormatterinstance, enable mathtext, set the desired precision, and match yourformatter.limitsconfiguration. - Assign the formatter to the secondary axis.
Modified code snippet:
import numpy as np from matplotlib import pyplot as plt from matplotlib import ticker # Add this import plt.rcParams['axes.formatter.limits'] = [-4, 6] plt.rcParams["axes.autolimit_mode"] = "round_numbers" plt.rcParams["axes.formatter.use_mathtext"] = True x = np.linspace(0, 4) y = np.linspace(0, 2.5) fig, ax = plt.subplots(dpi=300) ax.plot(x, y) secax = ax.twiny() axlim = ax.get_xlim() secax_xlim = [axlim[0]*22.76847e-6, axlim[1]*22.76847e-6] secax.set_xlim(secax_xlim) axticks = ax.get_xticks() secax_xtics = axticks*22.76847e-6 secax.xaxis.set_ticks(secax_xtics) # Customize secondary axis formatter formatter = ticker.ScalarFormatter(useMathText=True) formatter.set_precision(2) # Show 2 significant digits formatter.set_powerlimits((-4, 6)) # Match rcParam limits secax.xaxis.set_major_formatter(formatter) plt.show()
This will display ticks like $2.3 \times 10^{-5}$ (for 2 significant digits) or $2.28 \times 10^{-5}$ if you set precision=3.
Approach 2: Custom FuncFormatter for Exact Decimal Places
If you need exact decimal places in the mantissa (e.g., always 2 decimal places regardless of significant digits), create a custom FuncFormatter to format each tick value into mathtext-compliant scientific notation:
Modified code snippet:
import numpy as np from matplotlib import pyplot as plt from matplotlib import ticker # Add this import plt.rcParams['axes.formatter.limits'] = [-4, 6] plt.rcParams["axes.autolimit_mode"] = "round_numbers" plt.rcParams["axes.formatter.use_mathtext"] = True x = np.linspace(0, 4) y = np.linspace(0, 2.5) fig, ax = plt.subplots(dpi=300) ax.plot(x, y) secax = ax.twiny() axlim = ax.get_xlim() secax_xlim = [axlim[0]*22.76847e-6, axlim[1]*22.76847e-6] secax.set_xlim(secax_xlim) axticks = ax.get_xticks() secax_xtics = axticks*22.76847e-6 secax.xaxis.set_ticks(secax_xtics) # Custom formatter for exact 2 decimal places in mantissa def custom_format(value, tick_number): if value == 0: return r'$0$' # Format to 2 decimal places in scientific notation sci_str = "{0:.2e}".format(value) mantissa, exponent = sci_str.split('e') # Clean up exponent (remove leading zeros and plus sign) exponent = exponent.lstrip('+').lstrip('0') or '0' # Return mathtext-formatted string return r'$%s \times 10^{%s}$' % (mantissa, exponent) secax.xaxis.set_major_formatter(ticker.FuncFormatter(custom_format)) plt.show()
This will consistently display ticks like $2.28 \times 10^{-5}$ (exactly 2 decimal places in the mantissa) across all your charts, ensuring visual consistency.
Key Notes:
- Both methods preserve Matplotlib's mathtext rendering (e.g., proper superscript exponents).
- The
FuncFormatterapproach gives full control over decimal places, whileScalarFormatteradheres to significant digits (closer to Matplotlib's default behavior). - Adjust the
.2ein theFuncFormatterto.1efor 1 decimal place, or.3efor 3, etc.
内容的提问来源于stack exchange,提问作者tetukowski

