【问题标题】:How to preserve the resolution when adding axis using matplotlib.pyplot?使用 matplotlib.pyplot 添加轴时如何保持分辨率?
【发布时间】:2017-12-16 21:30:25
【问题描述】:

如果运行以下代码

import matplotlib.pyplot as plt
import numpy as np
a=np.random.random((1000,1000))
plt.imshow(a, cmap='Reds', interpolation='nearest')
plt.savefig('fig.png',bbox_inches='tight')

我得到了下面的图片,所有单元格代表每个随机数。

但是,当添加轴时如下代码所示:

import matplotlib.pyplot as plt
import numpy as np
a=np.random.random((1000,1000))
plt.imshow(a, cmap='Reds', interpolation='nearest')

plt.xlim(0, 10)
plt.xticks(list(range(0, 10)))
plt.ylim(0, 10)
plt.yticks(list(range(0, 10)))

plt.savefig('fig3.png',bbox_inches='tight')

我得到了分辨率较低的图片:

那么如何在不影响分辨率的情况下添加轴刻度?如果这与轴标记的字体大小有关,如何自动调整它们以保持原来的分辨率?

【问题讨论】:

  • 谢谢,但是如何将 100 标记为 1、200 标记为 2、....、1000 标记为 10?
  • 我在做一个例子。实际上,原始数据是皮秒,我想将其标记为纳秒。我想手动添加一些单词到刻度线,例如将“1,2,3”更改为“Atom 1,Atom 2,Atom 3”。

标签: python matplotlib resolution


【解决方案1】:

适用于您的问题:

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

a=np.random.random((1000,1000))

# create scaled formatters / for Y with Atom prefix
formatterY = FuncFormatter(lambda y, pos: 'Atom {0:g}'.format(y*0.01))
formatterX = FuncFormatter(lambda x, pos: '{0:g}'.format(x*0.01))

# apply formatters 
fig, ax = plt.subplots()
ax.yaxis.set_major_formatter(formatterY)
ax.xaxis.set_major_formatter(formatterX)

plt.imshow(a, cmap='Reds', interpolation='nearest')

# create labels
plt.xlabel('nanometer')
plt.ylabel('measure')
plt.xticks(list(range(0, 1001,100)))

plt.yticks(list(range(0, 1001,100)))

plt.show()

来源:

一种可能的解决方案是根据 matplotlib 页面的以下示例代码中的某些函数来格式化刻度标签。

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

x = np.arange(4)
money = [1.5e5, 2.5e6, 5.5e6, 2.0e7]


def millions(x, pos):
    'The two args are the value and tick position'
    return '$%1.1fM' % (x * 1e-6)


formatter = FuncFormatter(millions)

fig, ax = plt.subplots()
ax.yaxis.set_major_formatter(formatter)
plt.bar(x, money)
plt.xticks(x, ('Bill', 'Fred', 'Mary', 'Sue'))
plt.show()

matplotlib.org Example


this answer 中显示了类似的解决方案,其中 您可以设置一个函数来为您标记轴并按比例缩小:

ticks = ticker.FuncFormatter(lambda x, pos: '{0:g}'.format(x*scale))
ax.xaxis.set_major_formatter(ticks)

在这里,您需要使用/100 而不是*scale

对你来说更简单的方法可能是:

ticks = plt.xticks()/100
plt.gca().set_xticklabels(ticks.astype(int))

(改编自https://stackoverflow.com/a/10171851/7505395

【讨论】:

  • 谢谢,我得到了:AttributeError: module 'matplotlib.pyplot' has no attribute 'get_xticks'
  • 我试过了,但是标签挤在左边,分布不均匀。
  • 请注意,pylab 和 pyplot 提供的功能没有区别。 pylab 是一个包装器,它基本上由两行组成:from numpy import *; from matplotlib.pyplot import *。由于将多个包导入同一个命名空间并不是很好的风格,因此不推荐使用pylab。此答案中的所有解决方案都可以通过import matplotlib.pyplot as plt 工作。 (我修改了你的答案并删除了其中的错误。)
  • @ImportanceOfBeingErnest 感谢您的提示,将我的代码示例调整为 Q。
  • 谢谢,我在这里发帖link
【解决方案2】:

您将使用图像的extent 将其带入新的坐标空间。

目前它的范围在 0 到 999 之间。这意味着轴限制为 (-0.5, 999.5)。您可以从函数计算新范围,例如f = lambda x: x/100. 并将结果设置为图像的新范围。

这会使图像占据(-0.005, 9.995) 之间的轴范围。现在可以直接设置问题中看到的刻度(标签)。

import matplotlib.pyplot as plt
import numpy as np
a=np.random.random((1000,1000))

im = plt.imshow(a, cmap='Reds', interpolation='nearest')

f = lambda x: x/100.
(llx,ulx),(lly,uly) = plt.xlim(),plt.ylim()
im.set_extent([f(llx),f(ulx),f(lly),f(uly)])


plt.xticks(list(range(0, 10)))
plt.yticks(list(range(0, 10)))

plt.show()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-26
    • 1970-01-01
    • 2016-01-15
    • 2011-11-19
    • 2015-11-09
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多