matplotlib 如何设置对数图中孪生轴的刻度

ao218c7q  于 2023-10-24  发布在  其他
关注(0)|答案(3)|浏览(131)

在我的图中,辅助x轴用于显示某些数据的另一个变量的值。现在,原始轴是对数缩放的。不幸的是,孪生轴将刻度(和标签)放在原始轴的线性尺度上,而不是按照预期的对数尺度。如何克服这个问题?
下面的代码示例应该将孪生轴的刻度放在与原始轴相同的(绝对轴)位置:

def conv(x):
        """some conversion function"""
        # ...
        return x2

    ax = plt.subplot(1,1,1)
    ax.set_xscale('log')

    # get the location of the ticks of ax
    axlocs,axlabels = plt.xticks()

    # twin axis and set limits as in ax
    ax2 = ax.twiny()
    ax2.set_xlim(ax.get_xlim())

    #Set the ticks, should be set referring to the log scale of ax, but are set referring to the linear scale
    ax2.set_xticks(axlocs)

    # put the converted labels
    ax2.set_xticklabels(map(conv,axlocs))

另一种方法是(刻度不会设置在相同的位置,但这并不重要):

from matplotlib.ticker import FuncFormatter

    ax = plt.subplot(1,1,1)
    ax.set_xscale('log')

    ax2 = ax.twiny()
    ax2.set_xlim(ax.get_xlim())
    ax2.xaxis.set_major_formatter(FuncFormatter(lambda x,pos:conv(x)))

只要不使用对数标度,这两种方法都能很好地工作。
也许有一个简单的修复方法。我在文档中遗漏了什么吗?
作为一种变通方法,我尝试获取ax的刻度的ax.transAxes坐标,并将刻度放在ax2中的相同位置。

ax2.set_xticks(axlocs,transform=ax2.transAxes)
    TypeError: set_xticks() got an unexpected keyword argument 'transform'
piah890a

piah890a1#

这个问题已经问了一段时间了,但我被同样的问题绊倒了。
我最终通过引入一个logscaled(semilogx)透明(alpha=0)虚拟图来解决这个问题。
范例:

import numpy as np
import matplotlib.pyplot as plt

def conversion_func(x):  # some arbitrary transformation function
    return 2 * x**0.5        # from x to z

x = np.logspace(0, 5, 100)
y = np.sin(np.log(x))

fig = plt.figure()

ax = plt.gca()
ax.semilogx(x, y, 'k')
ax.set_xlim(x[0], x[-1])  # this is important in order that limits of both axes match
ax.set_ylabel("$y$")
ax.set_xlabel("$x$", color='C0')
ax.tick_params(axis='x', which='both', colors='C0')
ax.axvline(100, c='C0', lw=3)

ticks_x = np.logspace(0, 5, 5 + 1)  # must span limits of first axis with clever spacing
ticks_z = conversion_func(ticks_x)
ax2 = ax.twiny()  # get the twin axis
ax2.semilogx(ticks_z, np.ones_like(ticks_z), alpha=0)  # transparent dummy plot
ax2.set_xlim(ticks_z[0], ticks_z[-1])
ax2.set_xlabel("$z \equiv f(x)$", color='C1')
ax2.xaxis.label.set_color('C1')
ax2.tick_params(axis='x', which='both', colors='C1')
ax2.axvline(20, ls='--', c='C1', lw=3)  # z=20 indeed matches x=100 as desired

fig.show()

在上面的例子中,垂直线表明第一和第二轴确实按照需要彼此移动。x = 100被移动到z = 2*x**0.5 = 20。颜色只是为了澄清哪条垂直线与哪条轴相对应。

ggazkfy8

ggazkfy82#

不需要覆盖它们,只要消灭蜱虫!

d= [7,9,14,17,35,70];
j= [100,80,50,40,20,10];

plt.figure()
plt.xscale('log')
plt.plot(freq, freq*spec)  #plot some spectrum

ax1 = plt.gca()  #define my first axis 
ax1.yaxis.set_ticks_position('both')
ax1.tick_params(axis='y',which='both',direction='in');
ax1.tick_params(axis='x',which='both',direction='in');

ax2 = ax1.twiny()  #generates second axis (top) 
ax2.set_xlim(ax1.get_xlim());  #same limits
plt.xscale('log')  #make it log

ax2.set_xticks(freq[d]); #my own 'major' ticks OVERLAPS!!! 
ax2.set_xticklabels(j);  #change labels

ax2.tick_params(axis='x',which='major',direction='in'); 
ax2.tick_params(axis='x',which='minor',top=False); #REMOVE 'MINOR' TICKS
ax2.grid()
pgky5nke

pgky5nke3#

我想你可以通过调用ax2.set_xscale('log')来解决你的问题。

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots()

ax.semilogx(np.logspace(1.0, 5.0, 20), np.random.random([20]))

new_tick_locations = np.array([10., 100., 1000., 1.0e4])

def tick_function(X):
    V = X / 1000.
    return ["%.3f" % z for z in V]

ax2 = ax.twiny()
ax2.set_xscale('log')
ax2.set_xlim(ax.get_xlim())
ax2.set_xticks(new_tick_locations)
ax2.set_xticklabels(tick_function(new_tick_locations))
ax2.set_xlabel(r"Modified x-axis: $X/1000$")

相关问题