修改刻度标签文本

2024-12-06 08:39:00
admin
原创
99
摘要:问题描述:我想对图中选定的几个刻度标签进行一些修改。例如,如果我这样做:label = axes.yaxis.get_major_ticks()[2].label label.set_fontsize(size) label.set_rotation('vertical') 刻度标签的字体大小和方向发生了改变...

问题描述:

我想对图中选定的几个刻度标签进行一些修改。

例如,如果我这样做:

label = axes.yaxis.get_major_ticks()[2].label
label.set_fontsize(size)
label.set_rotation('vertical')

刻度标签的字体大小和方向发生了改变。

但是,如果尝试:

label.set_text('Foo')

勾选标签不会被修改。如果我这样做:

print label.get_text()

什么也没有打印。

这里还有一些奇怪的事情。当我尝试这样做时:

import matplotlib.pyplot as plt
import numpy as np

axes = plt.figure().add_subplot(111)
t = np.arange(0.0, 2.0, 0.01)
s = np.sin(2*np.pi*t)
axes.plot(t, s)
for ticklabel in axes.get_xticklabels():
    print(ticklabel.get_text())

仅打印空字符串,但图表包含标记为“0.0”、“0.5”、“1.0”、“1.5”和“2.0”的刻度。

在此处输入图片描述


解决方案 1:

警告:除非刻度标签已设置为字符串(通常在箱线图中如此),否则这将不适用于任何比 更新的 matplotlib 版本1.1.0。如果您使用当前的 github master,这将不起作用。我还不确定问题是什么……这可能是一个意外的变化,也可能不是……

通常情况下,你会采取如下做法:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

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

labels = [item.get_text() for item in ax.get_xticklabels()]
labels[1] = 'Testing'

ax.set_xticklabels(labels)

plt.show()

在此处输入图片描述

要理解为什么需要经历这么多麻烦,您需要更多地了解 matplotlib 的结构。

Matplotlib 刻意避免对刻度等进行“静态”定位,除非明确告知。假设您想要与绘图进行交互,因此绘图、刻度、刻度标签等的边界将动态变化。

因此,您不能只设置给定刻度标签的文本。默认情况下,每次绘制图表时,轴的定位器和格式化程序都会重新设置它。

但是,如果将定位器和格式化程序设置为静态(分别为FixedLocatorFixedFormatter),则刻度标签保持不变。

这就是set_*ticklabelsax.*axis.set_ticklabels做的事。

希望这能让您更清楚地了解为什么更改单个刻度标签有点复杂。

通常,您实际上想要做的只是注释某个位置。在这种情况下,请查看annotate

解决方案 2:

也可以使用pylabxticks来实现

import matplotlib
import matplotlib.pyplot as plt
x = [0,1,2]
y = [90,40,65]
labels = ['high', 'low', 37337]
plt.plot(x,y, 'r')
plt.xticks(x, labels, rotation='vertical')
plt.show()

https://matplotlib.org/stable/gallery/ticks_and_spines/ticklabels_rotation.html

解决方案 3:

在较新版本的 中matplotlib,如果您没有使用一组str值设置刻度标签,则默认情况下会使用它们''(绘制图时,标签只是刻度值)。知道这一点,要获得所需的输出,需要执行以下操作:

>>> from pylab import *
>>> axes = figure().add_subplot(111)
>>> a=axes.get_xticks().tolist()
>>> a[1]='change'
>>> axes.set_xticklabels(a)
[<matplotlib.text.Text object at 0x539aa50>, <matplotlib.text.Text object at 0x53a0c90>, 
<matplotlib.text.Text object at 0x53a73d0>, <matplotlib.text.Text object at 0x53a7a50>, 
<matplotlib.text.Text object at 0x53aa110>, <matplotlib.text.Text object at 0x53aa790>]
>>> plt.show()

结果:
在此处输入图片描述

现在如果你检查一下_xticklabels,它们不再是一堆了''

>>> [item.get_text() for item in axes.get_xticklabels()]
['0.0', 'change', '1.0', '1.5', '2.0']

1.1.1rc1它适用于从到当前版本的版本2.0

解决方案 4:

这个问题问了好久了。截至今天 ( matplotlib 2.2.2),经过一些阅读和尝试,我认为最佳/正确的方法是:

Matplotlib 有一个名为的模块ticker,其中包含支持完全可配置的刻度定位和格式化的类。要从图中修改特定刻度,以下方法对我有用:

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

def update_ticks(x, pos):
    if x == 0:
        return 'Mean'
    elif pos == 6:
        return 'pos is 6'
    else:
        return x

data = np.random.normal(0, 1, 1000)
fig, ax = plt.subplots()
ax.hist(data, bins=25, edgecolor='black')
ax.xaxis.set_major_formatter(mticker.FuncFormatter(update_ticks))
plt.show()

具有正态分布的随机值的直方图

警告! x是刻度的值,pos是其在轴上的相对位置。请注意,索引时pos取值从 开始1,而不是像往常一样从开始。0


就我而言,我试图y-axis用百分比值来格式化直方图。mticker有另一个名为的类PercentFormatter可以轻松执行此操作,而无需像以前那样定义单独的函数:

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

data = np.random.normal(0, 1, 1000)
fig, ax = plt.subplots()
weights = np.ones_like(data) / len(data)
ax.hist(data, bins=25, weights=weights, edgecolor='black')
ax.yaxis.set_major_formatter(mticker.PercentFormatter(xmax=1.0, decimals=1))
plt.show()

具有正态分布的随机值的直方图

在这种情况下,xmax是对应于 100% 的数据值。百分比计算为x / xmax * 100,这就是我们固定 的原因xmax=1.0。此外,decimals是小数点后要放置的小数位数。

解决方案 5:

这有效:

import matplotlib.pyplot as plt

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

x1 = [0,1,2,3]
squad = ['Fultz','Embiid','Dario','Simmons']

ax1.set_xticks(x1)
ax1.set_xticklabels(squad, minor=False, rotation=45)

联邦调查局

解决方案 6:

轴类有一个set_yticklabels函数,允许您设置刻度标签,如下所示:

#ax is the axes instance
group_labels = ['control', 'cold treatment',
             'hot treatment', 'another treatment',
             'the last one']

ax.set_xticklabels(group_labels)

我仍在研究为什么上面的例子不起作用。

解决方案 7:

这在 matplotlib 3 中也有效:

x1 = [0,1,2,3]
squad = ['Fultz','Embiid','Dario','Simmons']

plt.xticks(x1, squad, rotation=45)

解决方案 8:

如果您不使用figax并且想要修改所有标签(例如为了规范化),您可以这样做:

labels, locations = plt.yticks()
plt.yticks(labels, labels/max(labels))

解决方案 9:

尝试一下:

  fig,axis = plt.subplots(nrows=1,ncols=1,figsize=(13,6),sharex=True)
  axis.set_xticklabels(['0', 'testing', '10000', '20000', '30000'],fontsize=22)

解决方案 10:

在这里,我们打算修改一些刻度标签,Matplotlib但不会产生任何副作用,这样可以干净利落地工作,并保留偏移科学符号。此解决方案不会遇到其他一些答案中讨论的问题。

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

from matplotlib import rcParams
rcParams['axes.formatter.use_mathtext'] = True

class CustomScalarFormatter(matplotlib.ticker.ScalarFormatter):
    def __init__(self, useOffset=None, useMathText=None, useLocale=None, replace_values=([],[])):
        super().__init__(useOffset=None, useMathText=None, useLocale=None)
        self.replace_values = replace_values

    def __call__(self, x, pos=None):
        """
        Return the format for tick value *x* at position *pos*.
        """
        if len(self.locs) == 0:
            return ''
        elif x in self.replace_values[0]:
            idx = self.replace_values[0].index(x)
            return str(self.replace_values[1][idx])
        else:
            xp = (x - self.offset) / (10. ** self.orderOfMagnitude)
            if abs(xp) < 1e-8:
                xp = 0
            return self._format_maybe_minus_and_locale(self.format, xp)


z = np.linspace(0, 5000, 100)
fig, ax = plt.subplots()

xmajorformatter = CustomScalarFormatter(replace_values=([2000,0],['$x_0$','']))
ymajorformatter = CustomScalarFormatter(replace_values=([1E7,0],['$y_0$','']))
ax.xaxis.set_major_formatter(xmajorformatter)
ax.yaxis.set_major_formatter(ymajorformatter)

ax.plot(z,z**2)
plt.show()

我们在这里所做的是创建了matplotlib.ticker.ScalarFormatter类的派生类,matplotlib 默认使用该类来格式化标签。代码是从 matplotlib 源代码复制的,但只__call__复制并修改了函数。以下是

        elif x in self.replace_values[0]:
            idx = self.replace_values[0].index(x)
            return str(self.replace_values[1][idx])

是添加到函数中执行替换工作的新行__call__。派生类的优点是它继承了基类的所有功能,例如偏移量表示法、科学计数法标签(如果值很大)。结果是:

上述代码的输出

解决方案 11:

我注意到,这里发布的所有解决方案set_xticklabels()都没有保留偏移量,这是一个应用于刻度值的比例因子,用于创建更好看的刻度标签。例如,如果刻度在 0.00001 (1e-5) 的数量级,matplotlib 将自动添加比例因子 (或offset) 1e-5,因此最终的刻度标签可能最终为1 2 3 4,而不是1e-5 2e-5 3e-5 4e-5

下面给出一个例子:

数组xnp.array([1, 2, 3, 4])/1e6,且yy=x**2因此两者都是非常小的值。

左列:按照@Joe Kington 的建议,手动更改第 1 个和第 3 个标签。请注意,偏移量会丢失。

中间一列:与@iipr 建议的类似,使用FuncFormatter

右栏:我建议的偏移保留解决方案。

图如下:
在此处输入图片描述

完整代码在这里:

import matplotlib.pyplot as plt
import numpy as np

# create some *small* data to plot
x = np.arange(5)/1e6
y = x**2

fig, axes = plt.subplots(1, 3, figsize=(10,6))

#------------------The set_xticklabels() solution------------------
ax1 = axes[0]
ax1.plot(x, y)
fig.canvas.draw()
labels = [item.get_text() for item in ax1.get_xticklabels()]

# Modify specific labels
labels[1] = 'Testing'
labels[3] = 'Testing2'
ax1.set_xticklabels(labels)
ax1.set_title('set_xticklabels()')

#--------------FuncFormatter solution--------------
import matplotlib.ticker as mticker

def update_ticks(x, pos):
    if pos==1:
        return 'testing'
    elif pos==3:
        return 'testing2'
    else:
        return x

ax2=axes[1]
ax2.plot(x,y)
ax2.xaxis.set_major_formatter(mticker.FuncFormatter(update_ticks))
ax2.set_title('Func Formatter')

#-------------------My solution-------------------
def changeLabels(axis, pos, newlabels):
    '''Change specific x/y tick labels

    Args:
        axis (Axis): .xaxis or .yaxis obj.
        pos (list): indices for labels to change.
        newlabels (list): new labels corresponding to indices in <pos>.
    '''

    if len(pos) != len(newlabels):
        raise Exception("Length of <pos> doesn't equal that of <newlabels>.")

    ticks = axis.get_majorticklocs()
    # get the default tick formatter
    formatter = axis.get_major_formatter()
    # format the ticks into strings
    labels = formatter.format_ticks(ticks)

    # Modify specific labels
    for pii, lii in zip(pos, newlabels):
        labels[pii] = lii

    # Update the ticks and ticklabels. Order is important here.
    # Need to first get the offset (1e-6 in this case):
    offset = formatter.get_offset()
    # Then set the modified labels:
    axis.set_ticklabels(labels)
    # In doing so, matplotlib creates a new FixedFormatter and sets it to the xaxis
    # and the new FixedFormatter has no offset. So we need to query the
    # formatter again and re-assign the offset:
    axis.get_major_formatter().set_offset_string(offset)

    return

ax3 = axes[2]
ax3.plot(x, y)

changeLabels(ax3.xaxis, [1, 3], ['Testing', 'Testing2'])
ax3.set_title('With offset')

fig.show()
plt.savefig('tick_labels.png')

警告:似乎使用 的解决方案set_xticklabels()(包括我自己的解决方案)依赖于FixedFormatter,它是静态的并且不响应图形大小调整。要观察效果,​​请将图形更改为较小的尺寸,例如fig, axes = plt.subplots(1, 3, figsize=(6,6)),然后放大图形窗口。您会注意到,只有中间列响应调整大小,并且随着图形变大而添加更多刻度。左列和右列将有空的刻度标签(见下图)。

警告2:我还注意到,如果您的刻度值是浮点数,set_xticklabels(ticks)直接调用可能会给您带来难看的字符串,例如1.499999999998而不是1.5

在此处输入图片描述

解决方案 12:

  • matplotlib.axes.Axes.set_xticksmatplotlib.axes.Axes.set_yticksy 轴,可用于更改以 开头的刻度和标签 。这些用于面向对象的接口。
    matplotlib 3.5.0

    • 如果使用pyplot基于状态的接口,请使用plt.xticksplt.yticks,如其他答案所示。

    • 一般来说,将一个list/array数字传递给ticks参数,将一个list/array字符串传递给labels参数。

  • 在这种情况下,x 轴由连续的数值组成,因此没有设置文本标签,正如本答案中详细解释的那样。当绘图具有离散刻度(例如箱线图、条形图)时,情况并非如此。

    • [Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, ''), Text(0, 0, '')]返回的是ax.get_xticklabels()

    • [-0.25 0. 0.25 0.5 0.75 1. 1.25 1.5 1.75 2. 2.25]返回的是ax.get_xticks()

      • type(ax.get_xticks())<class 'numpy.ndarray'>

      • type(ax.get_xticks()[0])<class 'numpy.float64'>

  • 由于OP试图用替换数字标签str,因此必须将 中的所有值ndarray转换为str类型,然后才能更新要更改的值。

  • 经过python 3.10测试matplotlib 3.5.2

import numpy as np
import matplotlib.pyplot as plt

# create figure and axes
fig, ax = plt.subplots(figsize=(8, 6))

# plot data
t = np.arange(0.0, 2.0, 0.01)
s = np.sin(2*np.pi*t)

# plot
ax.plot(t, s)

# get the xticks, which are the numeric location of the ticks
xticks = ax.get_xticks()

# get the xticks and convert the values in the array to str type
xticklabels = list(map(str, ax.get_xticks()))

# update the string to be changed
xticklabels[1] = 'Test'

# set the xticks and the labels
_ = ax.set_xticks(xticks, xticklabels)

在此处输入图片描述

  • 请注意,更改 xticklabels 时不会保留 x 轴偏移量。但是,即使没有偏移量,也会显示正确的值。

# create figure and axes
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 6), sharex=False)

# plot data
t = np.linspace(0, 1500000, 100)
s = t**2

# plot
ax1.plot(t, s)
ax2.plot(t, s)

# get the xticks, which are the numeric location of the ticks
xticks = ax2.get_xticks()

# get the xticks and convert the values in the array to str type
xticklabels = list(map(str, ax2.get_xticks()))

# update the string to be changed
xticklabels[1] = 'Test'

# set the xticks and the labels
_ = ax2.set_xticks(xticks, xticklabels, rotation=90)

在此处输入图片描述

解决方案 13:

你可以这样做:

for k in ax.get_xmajorticklabels():
    if some-condition:
        k.set_color(any_colour_you_like)

draw()
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1008  
  在项目管理中,变更是一个不可避免的现象。无论是客户需求的调整、市场环境的变化,还是技术方案的更新,都可能引发项目的变更。如果处理不当,这些变更可能会导致项目延期、成本超支,甚至项目失败。因此,如何有效地应对项目变更,成为项目管理中的核心挑战之一。IPD(集成产品开发)作为一种高效的项目管理方法,其流程图不仅能够帮助团队...
IPD流程中的charter   0  
  IPD(Integrated Product Development,集成产品开发)是华为在长期实践中总结出的一套高效产品开发管理体系。它不仅帮助华为在全球市场中脱颖而出,也成为许多企业提升产品开发效率的参考标杆。IPD的核心在于通过跨部门协作、流程优化和资源整合,实现从需求分析到产品交付的全生命周期管理。通过实施IP...
IPD开发流程管理   0  
  华为IPD(集成产品开发)流程是一种以客户需求为导向、跨部门协同的高效项目管理方法。它通过系统化的流程设计和严格的阶段控制,确保项目从概念到交付的每个环节都能高效运作。IPD流程的核心在于打破传统职能部门的壁垒,将产品开发、市场、销售、供应链等关键环节整合到一个统一的框架中,从而实现资源的优化配置和信息的无缝流动。这种...
IPD流程中TR   0  
  在项目管理的实践中,CDCP(Certified Data Center Professional)认证评审是一个至关重要的环节。通过这一评审,项目团队不仅能够验证其数据中心设计和运营的合规性,还能提升整体管理水平。为了确保评审的顺利进行,准备一系列关键文档是必不可少的。这些文档不仅是评审的依据,也是项目团队与评审专家...
华为IPD是什么   0  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用