如何在没有对数缩放图像的情况下应用对数轴标签(matplotlib imshow)
How to apply logarithmic axis labels without log scaling image (matplotlib imshow)
我有一个呈对数分布的大型数据集。我想制作一个热图,所以我做了一个 2D 直方图并将其传递给 implot。因为数据是对数的,所以我将数据的日志传递给直方图。但是,当我绘制绘图时,我希望恢复轴(即 10^hist bin 值)和对数轴。如果我将轴设置为对数样式,则图像看起来都是倾斜的。当我将它传递给直方图时,数据已经是 'logged',所以我不希望图像受到影响,只希望轴受到影响。所以,在下面的例子中,我想要左边的图像和右边的轴。
我想我可以用一个假的叠加轴来做,但如果有更好的方法,我不喜欢做那种事情......
import numpy as np
import matplotlib.pyplot as plt
x=10**np.random.random(10000)*5
y=10**np.random.random(10000)*5
samps, xedges, yedges = np.histogram2d(np.log10(y), np.log10(x), bins=50)
ax = plt.subplot(121)
plt.imshow(samps, extent=[0,5,0,5])
plt.xlabel('Log10 X')
plt.ylabel('Log10 Y')
ax = plt.subplot(122)
plt.imshow(samps, extent=[10**0,10**5,10**0,10**5])
plt.xlabel('X')
plt.ylabel('Y')
plt.xscale('log')
plt.yscale('log')
plt.show()
您需要使用自定义格式化程序。这是 matplotlib 文档中的示例:
https://matplotlib.org/examples/pylab_examples/custom_ticker1.html
我倾向于使用 FuncFormatter
作为示例。主要技巧是您的函数需要接受参数 x
和 pos
。老实说,我不知道 pos
是干什么用的。也许甚至不是故意的,但你可以使用 FuncFormatter
作为装饰器,这就是我在下面所做的:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
@plt.FuncFormatter
def fake_log(x, pos):
'The two args are the value and tick position'
return r'^{%d}$' % (x)
x=10**np.random.random(10000)*5
y=10**np.random.random(10000)*5
samps, xedges, yedges = np.histogram2d(np.log10(y), np.log10(x), bins=50)
fig, (ax1) = plt.subplots()
ax1.imshow(samps, extent=[0, 5, 0, 5])
ax1.xaxis.set_major_formatter(fake_log)
ax1.yaxis.set_major_formatter(fake_log)
ax1.set_xlabel('X')
ax1.set_ylabel('Y')
如果您只想更改标签,可以通过 plt.gca().set_xticklabels
和 plt.gca().set_yticklabels
直接访问这些标签。这是一个简单的例子,改变了其中的 _text
属性。
import numpy as np
import matplotlib.pyplot as plt
x = 10 ** np.random.random(10000) * 5
y = 10 ** np.random.random(10000) * 5
samps, xedges, yedges = np.histogram2d(np.log10(y), np.log10(x), bins=50)
plt.subplot(121)
p = plt.imshow(samps, extent=[0, 5, 0, 5])
plt.xlabel('Log10 X')
plt.ylabel('Log10 Y')
plt.subplot(122)
p = plt.imshow(samps, extent=[0, 5, 0, 5])
# The label handling stuff starts here
plt.pause(0.5) # Needed to make sure the drawing finished being created
plt.xlabel('X')
plt.ylabel('Y')
plt.draw()
ax = plt.gca()
lbx = ax.get_xticklabels()
lby = ax.get_yticklabels()
for i in range(len(lbx)):
lbx[i]._text = r'^' + lbx[i]._text + '$'
for i in range(len(lby)):
lby[i]._text = r'^' + lby[i]._text + '$'
ax.set_xticklabels(lbx)
ax.set_yticklabels(lby)
plt.show()
我有一个呈对数分布的大型数据集。我想制作一个热图,所以我做了一个 2D 直方图并将其传递给 implot。因为数据是对数的,所以我将数据的日志传递给直方图。但是,当我绘制绘图时,我希望恢复轴(即 10^hist bin 值)和对数轴。如果我将轴设置为对数样式,则图像看起来都是倾斜的。当我将它传递给直方图时,数据已经是 'logged',所以我不希望图像受到影响,只希望轴受到影响。所以,在下面的例子中,我想要左边的图像和右边的轴。
我想我可以用一个假的叠加轴来做,但如果有更好的方法,我不喜欢做那种事情......
import numpy as np
import matplotlib.pyplot as plt
x=10**np.random.random(10000)*5
y=10**np.random.random(10000)*5
samps, xedges, yedges = np.histogram2d(np.log10(y), np.log10(x), bins=50)
ax = plt.subplot(121)
plt.imshow(samps, extent=[0,5,0,5])
plt.xlabel('Log10 X')
plt.ylabel('Log10 Y')
ax = plt.subplot(122)
plt.imshow(samps, extent=[10**0,10**5,10**0,10**5])
plt.xlabel('X')
plt.ylabel('Y')
plt.xscale('log')
plt.yscale('log')
plt.show()
您需要使用自定义格式化程序。这是 matplotlib 文档中的示例: https://matplotlib.org/examples/pylab_examples/custom_ticker1.html
我倾向于使用 FuncFormatter
作为示例。主要技巧是您的函数需要接受参数 x
和 pos
。老实说,我不知道 pos
是干什么用的。也许甚至不是故意的,但你可以使用 FuncFormatter
作为装饰器,这就是我在下面所做的:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
@plt.FuncFormatter
def fake_log(x, pos):
'The two args are the value and tick position'
return r'^{%d}$' % (x)
x=10**np.random.random(10000)*5
y=10**np.random.random(10000)*5
samps, xedges, yedges = np.histogram2d(np.log10(y), np.log10(x), bins=50)
fig, (ax1) = plt.subplots()
ax1.imshow(samps, extent=[0, 5, 0, 5])
ax1.xaxis.set_major_formatter(fake_log)
ax1.yaxis.set_major_formatter(fake_log)
ax1.set_xlabel('X')
ax1.set_ylabel('Y')
如果您只想更改标签,可以通过 plt.gca().set_xticklabels
和 plt.gca().set_yticklabels
直接访问这些标签。这是一个简单的例子,改变了其中的 _text
属性。
import numpy as np
import matplotlib.pyplot as plt
x = 10 ** np.random.random(10000) * 5
y = 10 ** np.random.random(10000) * 5
samps, xedges, yedges = np.histogram2d(np.log10(y), np.log10(x), bins=50)
plt.subplot(121)
p = plt.imshow(samps, extent=[0, 5, 0, 5])
plt.xlabel('Log10 X')
plt.ylabel('Log10 Y')
plt.subplot(122)
p = plt.imshow(samps, extent=[0, 5, 0, 5])
# The label handling stuff starts here
plt.pause(0.5) # Needed to make sure the drawing finished being created
plt.xlabel('X')
plt.ylabel('Y')
plt.draw()
ax = plt.gca()
lbx = ax.get_xticklabels()
lby = ax.get_yticklabels()
for i in range(len(lbx)):
lbx[i]._text = r'^' + lbx[i]._text + '$'
for i in range(len(lby)):
lby[i]._text = r'^' + lby[i]._text + '$'
ax.set_xticklabels(lbx)
ax.set_yticklabels(lby)
plt.show()