日志记录的 Matplotlib 坏刻度/标签(双轴) [英] Matplotlib bad ticks/labels for loglog (twin axis)

查看:51
本文介绍了日志记录的 Matplotlib 坏刻度/标签(双轴)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用matplotlib创建日志记录图.如下图所示,默认的价格变动选择得不好(充其量).右边的y轴根本没有任何东西(它在线性等效条件下没有),并且两个x轴都只有一个.

I'm creating loglog plots with matplotlib. As can be seen in the figure below, the default ticks are chosen badly (at best); the right y-axis doesn't even have any at all (it does in the linear equivalent) and both x-axis have only one.

有没有一种方法可以获得带有标签的合理数量的刻度, 无需为每个图手动指定它们?

Is there a way to get a reasonable number of ticks with labels, without specifying them by hand for every plot?

确切的代码太长,但这里有一个简短的问题示例:

the exact code is too long, but here's a short example of the problem:

x = linspace(4, 18, 20)
y = 1 / (x ** 4)
fig = figure()
ax = fig.add_axes([.1, .1, .8, .8])
ax.loglog(x, y)
ax.set_xlim([4, 18])
ax2 = ax.twiny()
ax2.set_xlim([4 / 3., 18 / 3.])
ax2.set_xscale('log')
show()

推荐答案

我一直在与显示的内容作斗争(在轴范围内只有一个主要刻度).matplotlib 刻度格式化程序中没有一个让我满意,所以我使用 matplotlib.ticker.FuncFormatter 来实现我想要的.我尚未用双轴进行测试,但我的感觉是无论如何它都可以工作.

I've been fighting with something like what you show (only one major tick in the axis range). None of the matplotlib tick formatter satisfied me, so I use matplotlib.ticker.FuncFormatter to achieve what I wanted. I haven't tested with twin axes, but my feeling is that it should work anyway.

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

#@Mark: thanks for the suggestion :D
mi, ma, conv = 4, 8, 1./3.
x = np.linspace(mi, ma, 20)
y = 1 / (x ** 4)

fig, ax = plt.subplots()

ax.plot(x, y)  # plot the lines
ax.set_xscale('log') #convert to log
ax.set_yscale('log')

ax.set_xlim([0.2, 1.8])  #large enough, but should show only 1 tick

def ticks_format(value, index):
    """
    This function decompose value in base*10^{exp} and return a latex string.
    If 0<=value<99: return the value as it is.
    if 0.1<value<0: returns as it is rounded to the first decimal
    otherwise returns $base*10^{exp}$
    I've designed the function to be use with values for which the decomposition
    returns integers
    """
    exp = np.floor(np.log10(value))
    base = value/10**exp
    if exp == 0 or exp == 1:
        return '${0:d}$'.format(int(value))
    if exp == -1:
        return '${0:.1f}$'.format(value)
    else:
        return '${0:d}\\times10^{{{1:d}}}$'.format(int(base), int(exp))

# here specify which minor ticks per decate you want
# likely all of them give you a too crowed axis
subs = [1., 3., 6.]
# set the minor locators
ax.xaxis.set_minor_locator(ticker.LogLocator(subs=subs))
ax.yaxis.set_minor_locator(ticker.LogLocator(subs=subs))
# remove the tick labels for the major ticks: 
# if not done they will be printed with the custom ones (you don't want it)
# plus you want to remove them to avoid font missmatch: the above function 
# returns latex string, and I don't know how matplotlib does exponents in labels
ax.xaxis.set_major_formatter(ticker.NullFormatter())
ax.yaxis.set_major_formatter(ticker.NullFormatter())
# set the desired minor tick labels using the above function
ax.xaxis.set_minor_formatter(ticker.FuncFormatter(ticks_format))
ax.yaxis.set_minor_formatter(ticker.FuncFormatter(ticks_format))

我得到的图如下:

当然,您可以为 x 和 y 轴设置不同的次定位器,并且您可以将所有内容从 ticks_format 包装到接受轴实例 ax 和末尾的函数中subssubsxsubsy 作为输入参数.

Of course you can set different minor locators for x and y axis and you can wrap everything from ticks_format to the end into a function that accepts an axes instance ax and subs or subsx and subsy as input parameters.

希望对你有帮助

这篇关于日志记录的 Matplotlib 坏刻度/标签(双轴)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆