Python Matplotlib 对数刻度刻度标签数字格式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21920233/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Matplotlib log scale tick label number formatting
提问by Nat Dempkowski
With matplotlibwhen a log scale is specified for an axis, the default method of labeling that axis is with numbers that are 10 to a power eg. 10^6. Is there an easy way to change all of these labels to be their full numerical representation? eg. 1, 10, 100, etc.
与matplotlib当对于一个轴被指定一个对数标度,标记该轴的默认方法是与是10到电源例如数字。10^6。有没有一种简单的方法可以将所有这些标签更改为它们的完整数字表示?例如。1、10、100 等
Note that I do not know what the range of powers will be and want to support an arbitrary range (negatives included).
请注意,我不知道权力的范围是多少,并希望支持任意范围(包括负数)。
采纳答案by Joe Kington
Sure, just change the formatter.
当然,只需更改格式化程序。
For example, if we have this plot:
例如,如果我们有这个图:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.axis([1, 10000, 1, 100000])
ax.loglog()
plt.show()


You could set the tick labels manually, but then the tick locations and labels would be fixed when you zoom/pan/etc. Therefore, it's best to change the formatter. By default, a logarithmic scale uses a LogFormatter, which will format the values in scientific notation. To change the formatter to the default for linear axes (ScalarFormatter) use e.g.
您可以手动设置刻度标签,但是当您缩放/平移/等时,刻度位置和标签将被固定。因此,最好更改格式化程序。默认情况下,对数刻度使用LogFormatter,它将以科学记数法格式化值。要将格式化程序更改为线性轴 ( ScalarFormatter)的默认值,请使用例如
from matplotlib.ticker import ScalarFormatter
for axis in [ax.xaxis, ax.yaxis]:
axis.set_major_formatter(ScalarFormatter())


回答by tmdavison
I've found that using ScalarFormatteris great if all your tick values are greater than or equal to 1. However, if you have a tick at a number <1, the ScalarFormatterprints the tick label as 0.
我发现,使用ScalarFormatter是伟大的,如果你所有的刻度值都大于或等于1。但是,如果你在一些有蜱<1,在ScalarFormatter打印刻度标记为0。
We can use a FuncFormatterfrom the matplotlib tickermodule to fix this issue. The simplest way to do this is with a lambdafunction and the gformat specifier (thanks to @lenz in comments).
我们可以使用FuncFormattermatplotlibticker模块中的 a 来解决这个问题。最简单的方法是使用lambda函数和g格式说明符(感谢@lenz 在评论中)。
import matplotlib.ticker as ticker
ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda y, _: '{:g}'.format(y)))
Note in my original answer I didn't use the gformat, instead I came up with this lambdafunction with FuncFormatterto set numbers >= 1to their integer value, and numbers <1to their decimal value, with the minimum number of decimal places required (i.e. 0.1, 0.01, 0.001, etc). It assumes that you are only setting ticks on the base10values.
请注意,在我的原始答案中,我没有使用g格式,而是提出了这个lambda函数,FuncFormatter用于将数字设置>= 1为整数值,将数字设置<1为十进制值,并具有所需的最小小数位数(即0.1, 0.01, 0.001,等)。它假设您只是在base10值上设置刻度。
import matplotlib.ticker as ticker
import numpy as np
ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda y,pos: ('{{:.{:1d}f}}'.format(int(np.maximum(-np.log10(y),0)))).format(y)))
For clarity, here's that lambda function written out in a more verbose, but also more understandable, way:
为清楚起见,下面是用更冗长但也更易于理解的方式写出的 lambda 函数:
def myLogFormat(y,pos):
# Find the number of decimal places required
decimalplaces = int(np.maximum(-np.log10(y),0)) # =0 for numbers >=1
# Insert that number into a format string
formatstring = '{{:.{:1d}f}}'.format(decimalplaces)
# Return the formatted tick label
return formatstring.format(y)
ax.yaxis.set_major_formatter(ticker.FuncFormatter(myLogFormat))
回答by litepresence
regarding these questions
关于这些问题
What if I wanted to change the numbers to, 1, 5, 10, 20?
– aloha Jul 10 '15 at 13:26I would like to add ticks in between, like 50,200, etc.., How can I do that? I tried, set_xticks[50.0,200.0] but that doesn't seem to work! – ThePredator Aug 3 '15 at 12:54
But with ax.axis([1, 100, 1, 100]), ScalarFormatter gives 1.0, 10.0, ... which is not what I desire. I want it to give integers... – CPBL Dec 7 '15 at 20:22
如果我想将数字更改为 1、5、10、20 怎么办?
– 阿罗哈 15 年 7 月 10 日 13:26我想在两者之间添加刻度,例如 50,200 等,我该怎么做?我试过, set_xticks[50.0,200.0] 但这似乎不起作用!– ThePredator 2015 年 8 月 3 日 12:54
但是使用 ax.axis([1, 100, 1, 100]),ScalarFormatter 给出 1.0, 10.0, ... 这不是我想要的。我希望它给出整数... – CPBL 2015 年 12 月 7 日 20:22
you can solve those issue like this with MINOR formatter:
您可以使用 MINOR 格式化程序解决这些问题:
ax.yaxis.set_minor_formatter(matplotlib.ticker.ScalarFormatter())
ax.yaxis.set_minor_formatter(matplotlib.ticker.FormatStrFormatter("%.8f"))
ax.set_yticks([0.00000025, 0.00000015, 0.00000035])
in my application I'm using this format scheme, which I think solves most issues related to log scalar formatting; the same could be done for data > 1.0 or x axis formatting:
在我的应用程序中,我使用了这种格式方案,我认为它解决了与日志标量格式相关的大多数问题;对于数据 > 1.0 或 x 轴格式也可以这样做:
plt.ylabel('LOGARITHMIC PRICE SCALE')
plt.yscale('log')
ax.yaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter())
ax.yaxis.set_major_formatter(matplotlib.ticker.FormatStrFormatter("%.8f"))
ax.yaxis.set_minor_formatter(matplotlib.ticker.ScalarFormatter())
ax.yaxis.set_minor_formatter(matplotlib.ticker.FormatStrFormatter("%.8f"))
#####################################################
#force 'autoscale'
#####################################################
yd = [] #matrix of y values from all lines on plot
for n in range(len(plt.gca().get_lines())):
line = plt.gca().get_lines()[n]
yd.append((line.get_ydata()).tolist())
yd = [item for sublist in yd for item in sublist]
ymin, ymax = np.min(yd), np.max(yd)
ax.set_ylim([0.9*ymin, 1.1*ymax])
#####################################################
z = []
for i in [0.0000001, 0.00000015, 0.00000025, 0.00000035,
0.000001, 0.0000015, 0.0000025, 0.0000035,
0.00001, 0.000015, 0.000025, 0.000035,
0.0001, 0.00015, 0.00025, 0.00035,
0.001, 0.0015, 0.0025, 0.0035,
0.01, 0.015, 0.025, 0.035,
0.1, 0.15, 0.25, 0.35]:
if ymin<i<ymax:
z.append(i)
ax.set_yticks(z)
for comments on "force autoscale" see:Python matplotlib logarithmic autoscale
有关“强制自动缩放”的评论,请参阅:Python matplotlib logarithmic autoscale
which yields:
产生:
then to create a general use machine:
然后创建一个通用机器:
# user controls
#####################################################
sub_ticks = [10,11,12,14,16,18,22,25,35,45] # fill these midpoints
sub_range = [-8,8] # from 100000000 to 0.000000001
format = "%.8f" # standard float string formatting
# set scalar and string format floats
#####################################################
ax.yaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter())
ax.yaxis.set_major_formatter(matplotlib.ticker.FormatStrFormatter(format))
ax.yaxis.set_minor_formatter(matplotlib.ticker.ScalarFormatter())
ax.yaxis.set_minor_formatter(matplotlib.ticker.FormatStrFormatter(format))
#force 'autoscale'
#####################################################
yd = [] #matrix of y values from all lines on plot
for n in range(len(plt.gca().get_lines())):
line = plt.gca().get_lines()[n]
yd.append((line.get_ydata()).tolist())
yd = [item for sublist in yd for item in sublist]
ymin, ymax = np.min(yd), np.max(yd)
ax.set_ylim([0.9*ymin, 1.1*ymax])
# add sub minor ticks
#####################################################
set_sub_formatter=[]
for i in sub_ticks:
for j in range(sub_range[0],sub_range[1]):
set_sub_formatter.append(i*10**j)
k = []
for l in set_sub_formatter:
if ymin<l<ymax:
k.append(l)
ax.set_yticks(k)
#####################################################
yields:
产量:
回答by Don Kirkby
I found Joe'sand Tom'sanswers very helpful, but there are a lot of useful details in the comments on those answers. Here's a summary of the two scenarios:
我发现Joe和Tom 的答案非常有帮助,但在这些答案的评论中有很多有用的细节。以下是两种情况的摘要:
Ranges above 1
范围大于 1
Here's the example code like Joe's, but with a higher range:
这是类似于 Joe 的示例代码,但范围更大:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.axis([1, 10000, 1, 1000000])
ax.loglog()
plt.show()
That shows a plot like this, using scientific notation:

As in Joe's answer, I use a ScalarFormatter, but I also call set_scientific(False). That's necessary when the scale goes up to 1000000 or above.
就像乔的回答一样,我使用了ScalarFormatter,但我也调用了set_scientific(False)。当规模达到 1000000 或更高时,这是必要的。
import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter
fig, ax = plt.subplots()
ax.axis([1, 10000, 1, 1000000])
ax.loglog()
for axis in [ax.xaxis, ax.yaxis]:
formatter = ScalarFormatter()
formatter.set_scientific(False)
axis.set_major_formatter(formatter)
plt.show()
Ranges below 1
低于 1 的范围
As in Tom's answer, here's what happens when the range goes below 1:
正如汤姆的回答,当范围低于 1 时会发生以下情况:
import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter
fig, ax = plt.subplots()
ax.axis([0.01, 10000, 1, 1000000])
ax.loglog()
for axis in [ax.xaxis, ax.yaxis]:
formatter = ScalarFormatter()
formatter.set_scientific(False)
axis.set_major_formatter(formatter)
plt.show()
That displays the first two ticks on the x axis as zeroes.
这将 x 轴上的前两个刻度显示为零。
Switching to a FuncFormatterhandles that. Again, I had problems with numbers 1000000 or higher, but adding a precision to the format string solved it.
切换到FuncFormatter处理那个。再次,我遇到了数字 1000000 或更高的问题,但向格式字符串添加精度解决了它。
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
fig, ax = plt.subplots()
ax.axis([0.01, 10000, 1, 1000000])
ax.loglog()
for axis in [ax.xaxis, ax.yaxis]:
formatter = FuncFormatter(lambda y, _: '{:.16g}'.format(y))
axis.set_major_formatter(formatter)
plt.show()

