Python Matplotlib:如何强制整数刻度标签?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30914462/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 09:09:45  来源:igfitidea点击:

Matplotlib: How to force integer tick labels?

pythonmatplotlibplot

提问by gha

My python script uses matplotlib to plot a 2D "heat map" of an x, y, z dataset. My x- and y-values represent amino acid residues in a protein and can therefore only be integers. When I zoom into the plot, it looks like this:

我的 python 脚本使用 matplotlib 绘制 x、y、z 数据集的二维“热图”。我的 x 和 y 值代表蛋白质中的氨基酸残基,因此只能是整数。当我放大情节时,它看起来像这样:

2D heat map with float tick marks

带有浮动刻度线的 2D 热图

As I said, float values on the x-y axes do not make sense with my data and I therefore want it to look like this: enter image description here

正如我所说,xy 轴上的浮点值对我的数据没有意义,因此我希望它看起来像这样: 在此处输入图片说明

Any ideas how to achieve this? This is the code that generates the plot:

任何想法如何实现这一目标?这是生成绘图的代码:

def plotDistanceMap(self):
    # Read on x,y,z
    x = self.currentGraph['xData']
    y = self.currentGraph['yData']
    X, Y = numpy.meshgrid(x, y)
    Z = self.currentGraph['zData']
    # Define colormap
    cmap = colors.ListedColormap(['blue', 'green', 'orange', 'red'])
    cmap.set_under('white')
    cmap.set_over('white')
    bounds = [1,15,50,80,100]
    norm = colors.BoundaryNorm(bounds, cmap.N)
    # Draw surface plot
    img = self.axes.pcolor(X, Y, Z, cmap=cmap, norm=norm)
    self.axes.set_xlim(x.min(), x.max())
    self.axes.set_ylim(y.min(), y.max())
    self.axes.set_xlabel(self.currentGraph['xTitle'])
    self.axes.set_ylabel(self.currentGraph['yTitle'])
    # Cosmetics
    #matplotlib.rcParams.update({'font.size': 12})
    xminorLocator = MultipleLocator(10)
    yminorLocator = MultipleLocator(10)
    self.axes.xaxis.set_minor_locator(xminorLocator)
    self.axes.yaxis.set_minor_locator(yminorLocator)
    self.axes.tick_params(direction='out', length=6, width=1)
    self.axes.tick_params(which='minor', direction='out', length=3, width=1)
    self.axes.xaxis.labelpad = 15
    self.axes.yaxis.labelpad = 15
    # Draw colorbar
    colorbar = self.figure.colorbar(img, boundaries = [0,1,15,50,80,100], 
                                    spacing = 'proportional',
                                    ticks = [15,50,80,100], 
                                    extend = 'both')
    colorbar.ax.set_xlabel('Angstrom')
    colorbar.ax.xaxis.set_label_position('top')
    colorbar.ax.xaxis.labelpad = 20
    self.figure.tight_layout()      
    self.canvas.draw()

采纳答案by Cédric Van Rompay

This should be simpler:

这应该更简单:

(from https://scivision.co/matplotlib-force-integer-labeling-of-axis/)

(来自https://scivision.co/matplotlib-force-integer-labeling-of-axis/

import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
#...
ax = plt.figure().gca()
#...
ax.xaxis.set_major_locator(MaxNLocator(integer=True))

回答by Andris

Based on an answer for modifying tick labelsI came up with a solution, don't know whether it will work in your case as your code snippet can't be executed in itself.

基于修改刻度标签的答案,我想出了一个解决方案,不知道它是否适用于您的情况,因为您的代码片段本身无法执行。

The idea is to force the tick labels to a .5 spacing, then replace every .5 tick with its integer counterpart, and others with an empty string.

这个想法是强制刻度标签为 0.5 间距,然后用它的整数对应物替换每个 0.5 刻度,并用空字符串替换其他刻度。

import numpy
import matplotlib.pyplot as plt

fig, (ax1, ax2) = plt.subplots(1,2)

x1, x2 = 1, 5
y1, y2 = 3, 7

# first axis: ticks spaced at 0.5
ax1.plot([x1, x2], [y1, y2])
ax1.set_xticks(numpy.arange(x1-1, x2+1, 0.5))
ax1.set_yticks(numpy.arange(y1-1, y2+1, 0.5))

# second axis: tick labels will be replaced
ax2.plot([x1, x2], [y1, y2])
ax2.set_xticks(numpy.arange(x1-1, x2+1, 0.5))
ax2.set_yticks(numpy.arange(y1-1, y2+1, 0.5))

# We need to draw the canvas, otherwise the labels won't be positioned and 
# won't have values yet.
fig.canvas.draw()

# new x ticks  '1'->'', '1.5'->'1', '2'->'', '2.5'->'2' etc.
labels = [item.get_text() for item in ax2.get_xticklabels()]
new_labels = [ "%d" % int(float(l)) if '.5' in l else '' for l in labels]
ax2.set_xticklabels(new_labels)

# new y ticks
labels = [item.get_text() for item in ax2.get_yticklabels()]
new_labels = [ "%d" % int(float(l)) if '.5' in l else '' for l in labels]
ax2.set_yticklabels(new_labels)

fig.canvas.draw()
plt.show()

If you want to zoom out a lot, that will need some extra care, as this one produces a very dense set of tick labels then.

如果你想缩小很多,那将需要一些额外的小心,因为这会产生一组非常密集的刻度标签。