matplotlib 在使用对数刻度时,使用科学计数法自定义刻度标签

sigwle7e  于 2023-11-22  发布在  其他
关注(0)|答案(2)|浏览(110)

我在使用matplotlib(3.1.3版)时遇到了问题:我想在保留科学计数法的同时,在对数刻度轴上添加自定义刻度和刻度标签。
换句话说:我想在对数刻度轴上添加自定义刻度,并使用良好的老式'%1.1e'(或任何数字)格式标记它们,但是,例如,我希望使用'2.5 x 10^-2'(或乳胶中的'2.5 \times 10^{-2}')而不是'2.5e-02'。
所以我从一段最小的工作代码开始,没有自定义记号:

import matplotlib as mpl
import matplotlib.pyplot as plt
print('MATPLOTLIB  VERSION : %s' % mpl.__version__)

plt.style.use("default")

# DATA
x = [0.1, 0.075, 0.05, 0.025, 0.01, 0.0075, 0.005, 0.0025, 0.001, 0.00075, 0.0005, 0.00025, 0.0001, 7.5e-05, 5e-05, 2.5e-05, 1e-05, 1e-06, 1e-07, 1e-08, 1e-09, 1e-10]
y = x

fig = plt.figure()
ax = plt.axes()
plt.loglog()
plt.minorticks_off()
path = ax.plot(x, y)

plt.savefig('test.png')

字符串
其给出:
x1c 0d1x的数据
很好,但是,正如我所说的,我想在x轴上添加自定义刻度。更准确地说,我想在轴上设置限制,并在这些限制之间定义等对数间隔的标签。假设我想要4个刻度;它给出了以下代码:

import matplotlib as mpl
import matplotlib.pyplot as plt
print('MATPLOTLIB  VERSION : %s' % mpl.__version__)

plt.style.use("default")

# DATA
x = [0.1, 0.075, 0.05, 0.025, 0.01, 0.0075, 0.005, 0.0025, 0.001, 0.00075, 0.0005, 0.00025, 0.0001, 7.5e-05, 5e-05, 2.5e-05, 1e-05, 1e-06, 1e-07, 1e-08, 1e-09, 1e-10]
y = x

xmin = min(x)
xmax = max(x)
ymin = min(y)
ymax = max(y)

# XTICKS
nbdiv = 4
xTicks = []
k = pow((xmin/xmax),1./(nbdiv-1.))
for i in range(0,nbdiv):
  xTicks.append(xmax*pow(k,i))

# PLOT
fig = plt.figure()
ax = plt.axes()
plt.loglog()
plt.minorticks_off()
plt.axis([xmin,xmax,ymin,ymax])
plt.xticks(xTicks)
path = ax.plot(x, y)

plt.savefig('test_working_4.png')


它提供了以下图表:



这就是我想要得到的结果。然而,如果tick的数量(nbdiv)改变,例如变成5,我得到:



这一次,只有第一个和最后一个刻度被标记。似乎只有等于(或至少接近)10的整数次幂(10^n)的数字被标记。我试图用matplot.ticker.ScalarFormatter更改默认刻度格式,但我没有设法调整它来解决这个问题。我也尝试了LogisterMathText和LogisterSciNotation,它并没有更好。
这个问题本身对我来说似乎并不困难,所以我不明白为什么我有这么多的麻烦..
在任何情况下,我感谢你的阅读,我提前感谢你的回应。
P.S.:对不起,可能会出现英语错误,这不是我的母语。

lskq00tm

lskq00tm1#

解决了,基于你上面的代码。这个简单得多。你需要使用xticklabels。

%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
from sympy import pretty_print as pp, latex
print('MATPLOTLIB  VERSION : %s' % mpl.__version__)

plt.style.use("default")

# DATA
x = [0.1, 0.075, 0.05, 0.025, 0.01, 0.0075, 0.005, 0.0025, 0.001, 0.00075, 0.0005, 0.00025, 0.0001, 7.5e-05, 5e-05, 2.5e-05, 1e-05, 1e-06, 1e-07, 1e-08, 1e-09, 1e-10]
y = x

xmin = min(x)
xmax = max(x)
ymin = min(y)
ymax = max(y)

# XTICKS
nbdiv = 5
xTicks = []
xticklabels = []
k = pow((xmin/xmax),1./(nbdiv-1.))
for i in range(0,nbdiv):
  xTicks.append(xmax*pow(k,i))
  printstr = '{:.2e}'.format(xmax*pow(k,i))
  ls = printstr.split('e')
  xticklabels.append((ls[0]+' x $10^{'  +ls[1] + '}$'))

# PLOT
fig = plt.figure()
ax = plt.axes()
plt.loglog()
plt.minorticks_off()
plt.axis([xmin,xmax,ymin,ymax])
plt.xticks(xTicks)
path = ax.plot(x, y)

plt.savefig('test_working_4.png')
ax.set_xticklabels(xticklabels)

字符串


的数据

gkl3eglg

gkl3eglg2#

很抱歉重复发布,但我带来了一个解决方案,即使不满意,可能对其他人有用。
我发现我的解决方案并不令人满意,因为它涉及到用我的以下函数“手工”转换格式(我不是PythonMaven,所以我相信它可以被简化/优化):

def convert_e_format_to_latex(numberAsStr):
# CONVERTS THE STRING numberAsStr IN FORMAT '%X.Ye' TO A LATEX 'X \\times 10^{Y}'
  baseStr = list(numberAsStr)
  ind = 0
  i = 0
  flag = True
  nStr = len(baseStr)
  while (i < nStr and flag):
    if (baseStr[i] == 'e' or baseStr[i] == 'E'): # NOT USING FIND BECAUSE 'e' CAN ALSO BE CAPITAL
      ind = i
      flag = False
    i += 1
  if (flag):
    print('ERROR: badly formatted input number')
    return ''
  else:
    expo = str(int(''.join(baseStr[ind+1:nStr]))) # GET RID OF POTENTIAL ZEROS
    root = ''.join(baseStr[0:ind])
    indP = root.find('.')
    integerPart = int(root[0:indP]) #integer
    decimalPart = root[indP+1:ind] #string
    if (integerPart == 1): #DETECTING IF THE ROOT IS ONE (positive value)
      x = ''.center(ind-(indP+1),'0')
      if (decimalPart == x):
        return '$10^{'+expo+'}$'
      else:
        return '$'+str(integerPart)+'.'+decimalPart+' \\times 10^{'+expo+'}$'
    elif (integerPart== -1): #DETECTING IF THE ROOT IS ONE (positive value)
      x = ''.center(ind-(indP+1),'0')
      if (decimalPart == x):
        return '$-10^{'+expo+'}$'
      else:
        return '$'+str(integerPart)+'.'+decimalPart+' \\times 10^{'+expo+'}$'
    else:
      return '$'+str(integerPart)+'.'+decimalPart+' \\times 10^{'+expo+'}$'

字符串
然后我在前面的代码中添加:

for i in range(0,nbdiv):
  xTicksStr.append(convert_e_format_to_latex('%1.1e'%xTicks[i]))


我将绘图中的xticks指令更改为:

plt.xticks(xTicks,xTicksStr)


这给出了想要的输出:
x1c 0d1x的数据
它工作,但它是如此复杂.我很确定我错过了一个更简单的功能.你怎么看?

相关问题