【问题标题】:Changing the "tick frequency" on x or y axis in matplotlib在 matplotlib 中更改 x 或 y 轴上的“滴答频率”
【发布时间】:2021-08-04 20:58:42
【问题描述】:

我正在尝试修复 python 如何绘制我的数据。

x = [0,5,9,10,15]

y = [0,1,2,3,4]

那么我会这样做:

matplotlib.pyplot.plot(x,y)
matplotlib.pyplot.show()

并且 x 轴的刻度以 5 的间隔绘制。有没有办法让它显示 1 的间隔?

【问题讨论】:

  • 虽然 ticks 在这里是合适的词,但是将 ticks 改为 step size 肯定会引导更多新手回答这个问题。
  • 密切相关的问题:stackoverflow.com/questions/6682784/… 和一个很好的解决方案:pyplot.locator_params(nbins=4)

标签: python matplotlib plot axes xticks


【解决方案1】:

您可以使用plt.xticks 明确设置您想要标记的位置:

plt.xticks(np.arange(min(x), max(x)+1, 1.0))

例如,

import numpy as np
import matplotlib.pyplot as plt

x = [0,5,9,10,15]
y = [0,1,2,3,4]
plt.plot(x,y)
plt.xticks(np.arange(min(x), max(x)+1, 1.0))
plt.show()

(使用np.arange 而不是Python 的range 函数,以防min(x)max(x) 是浮点数而不是整数。)


plt.plot(或ax.plot)函数将自动设置默认xy 限制。如果您希望保持这些限制,并且只是更改刻度线的步长,那么您可以使用 ax.get_xlim() 来发现 Matplotlib 已经设置的限制。

start, end = ax.get_xlim()
ax.xaxis.set_ticks(np.arange(start, end, stepsize))

默认的刻度格式化程序应该可以将刻度值四舍五入到合理的有效数字位数。但是,如果您希望对格式有更多的控制,您可以定义自己的格式化程序。例如,

ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%0.1f'))

这是一个可运行的示例:

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

x = [0,5,9,10,15]
y = [0,1,2,3,4]
fig, ax = plt.subplots()
ax.plot(x,y)
start, end = ax.get_xlim()
ax.xaxis.set_ticks(np.arange(start, end, 0.712123))
ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%0.1f'))
plt.show()

【讨论】:

  • 有没有办法让它仍然决定它自己的限制,而只是改变步长?如果 min 是 3523.232512 之类的,这种方法不是很好!
  • @Corone,你问已经有一段时间了,但我在下面发布了一个答案,可以在仍然使用自动边界确定的同时轻松控制步长。
  • 请注意,plt.xticks(np.arange(min(x), max(x)+1, 1.0)) 中的 +1 是显示最后一个刻度线所必需的。
  • 是的,np.arange(start, stop)半开 区间 [start, stop) 中生成值,包括 start 但不包括 stop。所以我使用max(x)+1 来确保包含max(x)
  • 日期时间是否有等价物,例如plt.xticks(np.arange(min(dates), max(dates)+0.1,0.1) ?它似乎只绘制年份
【解决方案2】:

另一种方法是设置轴定位器:

import matplotlib.ticker as plticker

loc = plticker.MultipleLocator(base=1.0) # this locator puts ticks at regular intervals
ax.xaxis.set_major_locator(loc)

根据您的需要,有几种不同类型的定位器。

这是一个完整的例子:

import matplotlib.pyplot as plt
import matplotlib.ticker as plticker

x = [0,5,9,10,15]
y = [0,1,2,3,4]
fig, ax = plt.subplots()
ax.plot(x,y)
loc = plticker.MultipleLocator(base=1.0) # this locator puts ticks at regular intervals
ax.xaxis.set_major_locator(loc)
plt.show()

【讨论】:

  • 这不能按预期工作。具体来说,在使用日期时,它不会使用适当的日期。
  • 使用日期时,应使用 matplotlib.dates 模块中的方法。例如matplotlib.dates.AutoDateLocator()
  • 它按我的预期工作,有日期。此解决方案比公认的解决方案容易得多。
  • base=1.0 究竟是什么意思/做什么?
  • base=1.0 表示每个整数都有一个定位器。文档说 MultipleLocator “在视图间隔内为每个基数的整数倍设置一个刻度。”。因此,如果 base=2,那么偶数会打勾,我认为您可以设置 base=2.5。
【解决方案3】:

我喜欢这个解决方案(来自Matplotlib Plotting Cookbook):

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

x = [0,5,9,10,15]
y = [0,1,2,3,4]

tick_spacing = 1

fig, ax = plt.subplots(1,1)
ax.plot(x,y)
ax.xaxis.set_major_locator(ticker.MultipleLocator(tick_spacing))
plt.show()

此解决方案可让您通过ticker.MultipleLocater() 提供的数字显式控制刻度间距,允许自动确定限制,并且以后易于阅读。

【讨论】:

  • 一种无需明确计算刻度的方法!
  • 这与this one 的答案相同。两年后添加相同的答案是没有意义的。
  • 好收获。当我发布答案时,我没有认识到它们是一样的。不过,我认为这个演示文稿更容易​​理解。
  • 此答案中的书籍参考也提供了有用的信息来源。
  • 这与三年前出现的robochat的答案相同。
【解决方案4】:

如果有人对通用单线感兴趣,只需获取当前刻度并使用它通过每隔一个刻度采样来设置新刻度。

ax.set_xticks(ax.get_xticks()[::2])

【讨论】:

  • 这是针对不同刻度类型(str、float、datetime)的唯一通用答案
  • 删除非整数刻度:ax.set_xticks([tick for tick in ax.get_xticks() if tick % 1 == 0])
  • 上面有很多详细的解决方案,但我同意这是最简洁的。您甚至可以提取 ax.get_xticks() 的长度,然后将切片频率除以该长度除以所需的刻度数。
  • 我认为这是最好的答案。大多数其他答案太复杂,难以应用/概括。谢谢!
  • 它只能减少棍子的数量,而问题(以及我如何找到它的目标)是增加它。
【解决方案5】:

这有点老套,但到目前为止,我发现这样做是最干净/最容易理解的示例。这是来自这里的答案:

Cleanest way to hide every nth tick label in matplotlib colorbar?

for label in ax.get_xticklabels()[::2]:
    label.set_visible(False)

然后你可以循环标签,根据你想要的密度将它们设置为可见或不可见。

编辑:请注意,有时 matplotlib 设置标签 == '',因此看起来标签不存在,而实际上它存在并且只是不显示任何内容。为确保您循环显示实际可见的标签,您可以尝试:

visible_labels = [lab for lab in ax.get_xticklabels() if lab.get_visible() is True and lab.get_text() != '']
plt.setp(visible_labels[::2], visible=False)

【讨论】:

  • 这是最简单通用的解决方案。一个微小的调整:通常ax.get_xticklabels()[1::2] 是要隐藏的标签。
  • 这不适用于 matplotlib.finance.candlestick2
  • @BCR 可能是某些 xticklabels 只是设置为 '' 因此,当您遍历它们时,您正在使 xticklabels 是空的不可见(这对可视化,但可能意味着您没有拉出正确的标签)。你可以试试:vis_labels = [label for label in ax.get_xticklabels() if label.get_visible() is True]; plt.setp(vis_labels[::2], visible==False)
【解决方案6】:

如果你只是想用最少的样板来设置一个简单的单行:

plt.gca().xaxis.set_major_locator(plt.MultipleLocator(1))

也适用于小蜱:

plt.gca().xaxis.set_minor_locator(plt.MultipleLocator(1))

有点满口,但很紧凑

【讨论】:

    【解决方案7】:

    这是一个老话题,但我时不时地偶然发现这个并制作了这个功能。很方便:

    import matplotlib.pyplot as pp
    import numpy as np
    
    def resadjust(ax, xres=None, yres=None):
        """
        Send in an axis and I fix the resolution as desired.
        """
    
        if xres:
            start, stop = ax.get_xlim()
            ticks = np.arange(start, stop + xres, xres)
            ax.set_xticks(ticks)
        if yres:
            start, stop = ax.get_ylim()
            ticks = np.arange(start, stop + yres, yres)
            ax.set_yticks(ticks)
    

    像这样控制刻度的一个警告是,在添加线后,人们不再享受最大比例的交互式自动更新。然后做

    gca().set_ylim(top=new_top) # for example
    

    然后再次运行 resadjust 函数。

    【讨论】:

      【解决方案8】:

      我开发了一个不优雅的解决方案。假设我们有 X 轴以及 X 中每个点的标签列表。

      例子:
      import matplotlib.pyplot as plt
      
      x = [0,1,2,3,4,5]
      y = [10,20,15,18,7,19]
      xlabels = ['jan','feb','mar','apr','may','jun']
      
      假设我只想显示 'feb' 和 'jun' 的刻度标签
      xlabelsnew = []
      for i in xlabels:
          if i not in ['feb','jun']:
              i = ' '
              xlabelsnew.append(i)
          else:
              xlabelsnew.append(i)
      
      很好,现在我们有一个虚假的标签列表。首先,我们绘制了原始版本。
      plt.plot(x,y)
      plt.xticks(range(0,len(x)),xlabels,rotation=45)
      plt.show()
      
      现在,修改后的版本。
      plt.plot(x,y)
      plt.xticks(range(0,len(x)),xlabelsnew,rotation=45)
      plt.show()
      

      【讨论】:

        【解决方案9】:

        纯 Python 实现

        以下是所需功能的纯 python 实现,可处理具有正数、负数或混合值的任何数字系列(int 或 float),并允许用户指定所需的步长:

        import math
        
        def computeTicks (x, step = 5):
            """
            Computes domain with given step encompassing series x
            @ params
            x    - Required - A list-like object of integers or floats
            step - Optional - Tick frequency
            """
            xMax, xMin = math.ceil(max(x)), math.floor(min(x))
            dMax, dMin = xMax + abs((xMax % step) - step) + (step if (xMax % step != 0) else 0), xMin - abs((xMin % step))
            return range(dMin, dMax, step)
        

        样本输出

        # Negative to Positive
        series = [-2, 18, 24, 29, 43]
        print(list(computeTicks(series)))
        
        [-5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
        
        # Negative to 0
        series = [-30, -14, -10, -9, -3, 0]
        print(list(computeTicks(series)))
        
        [-30, -25, -20, -15, -10, -5, 0]
        
        # 0 to Positive
        series = [19, 23, 24, 27]
        print(list(computeTicks(series)))
        
        [15, 20, 25, 30]
        
        # Floats
        series = [1.8, 12.0, 21.2]
        print(list(computeTicks(series)))
        
        [0, 5, 10, 15, 20, 25]
        
        # Step – 100
        series = [118.3, 293.2, 768.1]
        print(list(computeTicks(series, step = 100)))
        
        [100, 200, 300, 400, 500, 600, 700, 800]
        

        示例用法

        import matplotlib.pyplot as plt
        
        x = [0,5,9,10,15]
        y = [0,1,2,3,4]
        plt.plot(x,y)
        plt.xticks(computeTicks(x))
        plt.show()
        

        请注意,x 轴的整数值均以 5 为间隔,而 y 轴的间隔不同(matplotlib 默认行为,因为未指定刻度)。

        【讨论】:

          【解决方案10】:
          xmarks=[i for i in range(1,length+1,1)]
          
          plt.xticks(xmarks)
          

          这对我有用

          如果你想要 [1,5](包括 1 和 5)之间的刻度,则替换

          length = 5
          

          【讨论】:

          • 仅供参考,您可以简单地写xmarks = range(1, length+1, 1)。很确定列表理解是多余的。
          【解决方案11】:

          由于上述解决方案没有一个适用于我的用例,因此我在此提供了一个使用 None(双关语!)的解决方案,它可以适应各种场景。

          这是一段代码示例,它在 XY 轴上产生杂乱的刻度。

          # Note the super cluttered ticks on both X and Y axis.
          
          # inputs
          x = np.arange(1, 101)
          y = x * np.log(x) 
          
          fig = plt.figure()     # create figure
          ax = fig.add_subplot(111)
          ax.plot(x, y)
          ax.set_xticks(x)        # set xtick values
          ax.set_yticks(y)        # set ytick values
          
          plt.show()
          

          现在,我们用一个新图来清理混乱,该图仅将 x 和 y 轴上的一组稀疏值显示为刻度。

          # inputs
          x = np.arange(1, 101)
          y = x * np.log(x)
          
          fig = plt.figure()       # create figure
          ax = fig.add_subplot(111)
          ax.plot(x, y)
          
          ax.set_xticks(x)
          ax.set_yticks(y)
          
          # which values need to be shown?
          # here, we show every third value from `x` and `y`
          show_every = 3
          
          sparse_xticks = [None] * x.shape[0]
          sparse_xticks[::show_every] = x[::show_every]
          
          sparse_yticks = [None] * y.shape[0]
          sparse_yticks[::show_every] = y[::show_every]
          
          ax.set_xticklabels(sparse_xticks, fontsize=6)   # set sparse xtick values
          ax.set_yticklabels(sparse_yticks, fontsize=6)   # set sparse ytick values
          
          plt.show()
          

          根据用例,可以通过更改show_every 并使用该代码对 X 或 Y 或两个轴的刻度值进行采样来调整上述代码。

          如果这个基于步长的解决方案不适合,那么也可以不定期地填充sparse_xtickssparse_yticks 的值,如果这是需要的话。

          【讨论】:

            【解决方案12】:

            可通用的一个班轮,仅导入 Numpy:

            import numpy as np
            ax.set_xticks(np.arange(min(ax.get_xticks()),max(ax.get_xticks()),1));
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-07-28
              • 2022-01-04
              • 2010-11-11
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多