Matplotlib对数刻度标签,LaTeX字体中的负号过长

3 投票
2 回答
2803 浏览
提问于 2025-04-18 16:36

我在使用matplotlib的时候,把'text.usetex'设置成了True。这样在画线性比例的图时效果很好。但是在画对数比例的图时,y轴的刻度看起来是这样的:

你会发现,指数中的负号占用了很多水平空间,这样看起来不太好。我希望它能看起来像这样:

这个图是从gnuplot生成的,它没有使用tex字体。我想用matplotlib来画图,使用tex渲染,但10^{-n}中的负号应该短一些。这样可以做到吗?

2 个回答

5

负号的长度是由你使用的LaTeX字体决定的。在数学模式下,二元负号和一元负号的长度是一样的。根据这个回答,你可以自己制作标签。试试这个:

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


mpl.rcParams['text.usetex']=True
mpl.rcParams['text.latex.unicode']=True

def my_formatter_fun(x, p):
    """ Own formatting function """
    return r"$10$\textsuperscript{%i}" % np.log10(x)  #  raw string to avoid "\\"


x = np.linspace(1e-6,1,1000)
y = x**2

fg = plt.figure(1); fg.clf()
ax = fg.add_subplot(1, 1, 1)
ax.semilogx(x, x**2)
ax.set_title("$10^{-3}$ versus $10$\\textsuperscript{-3} versus "
             "10\\textsuperscript{-3}")
# Use own formatter:
ax.get_xaxis().set_major_formatter(ticker.FuncFormatter(my_formatter_fun))

fg.canvas.draw()
plt.show()

这样可以得到:结果图

4

Dietrich给了你一个不错的答案,但如果你想保留LogFormatter的所有功能(比如非十进制、非整数的指数),那么你可以自己创建一个格式化器:

import matplotlib.ticker
import matplotlib
import re

# create a definition for the short hyphen
matplotlib.rcParams["text.latex.preamble"].append(r'\mathchardef\mhyphen="2D')

class MyLogFormatter(matplotlib.ticker.LogFormatterMathtext):
    def __call__(self, x, pos=None):
        # call the original LogFormatter
        rv = matplotlib.ticker.LogFormatterMathtext.__call__(self, x, pos)

        # check if we really use TeX
        if matplotlib.rcParams["text.usetex"]:
            # if we have the string ^{- there is a negative exponent
            # where the minus sign is replaced by the short hyphen
            rv = re.sub(r'\^\{-', r'^{\mhyphen', rv)

        return rv

这个格式化器的主要作用是获取常规格式化器的输出,找到可能的负指数,然后把数学公式中的减号的LaTeX代码换成其他的东西。当然,如果你想用\scalebox或者类似的东西来创造一些有趣的LaTeX效果,也是可以的。

这个:

import matplotlib.pyplot as plt
import numpy as np

matplotlib.rcParams["text.usetex"] = True
fig = plt.figure()
ax = fig.add_subplot(111)
ax.semilogy(np.linspace(0,5,200), np.exp(np.linspace(-2,3,200)*np.log(10)))
ax.yaxis.set_major_formatter(MyLogFormatter())
fig.savefig("/tmp/shorthyphen.png")

会生成:

在这里输入图片描述

这个解决方案的好处在于,它尽量减少了输出的变化。

撰写回答