【问题标题】:Highlighting arbitrary points in a matplotlib plot在 matplotlib 图中突出显示任意点
【发布时间】:2017-08-09 21:04:49
【问题描述】:

我是 python 和 matplotlib 的新手。

我正在尝试在 matplotlib 中已存在的图中突出显示符合特定标准的一些点。

初始情节的代码如下:

pl.plot(t,y)
pl.title('Damped Sine Wave with %.1f Hz frequency' % f)
pl.xlabel('t (s)')
pl.ylabel('y')
pl.grid()
pl.show()

在上面的图中,我想突出显示一些符合标准 abs(y)>0.5 的特定点。提出要点的代码如下:

markers_on = [x for x in y if abs(x)>0.5]

我尝试使用参数“markevery”,但它会引发错误提示

'markevery' is iterable but not a valid form of numpy fancy indexing;

给出错误的代码如下:

pl.plot(t,y,'-gD',markevery = markers_on)
pl.title('Damped Sine Wave with %.1f Hz frequency' % f)
pl.xlabel('t (s)')
pl.ylabel('y')
pl.grid()
pl.show()

【问题讨论】:

    标签: python-3.x matplotlib


    【解决方案1】:

    绘图函数的markevery 参数接受不同类型的输入。根据输入类型,它们的解释不同。在this matplotlib example 中找到一份不错的可能性列表。

    如果您有条件显示标记,则有两种选择。假设 ty 是 numpy 数组,其中一个有 imported numpy as np

    1. 要么指定布尔数组

      plt.plot(t,y,'-gD',markevery = np.where(y > 0.5, True, False))
      

    1. 索引数组

      plt.plot(t,y,'-gD',markevery = np.arange(len(t))[y > 0.5])
      

    完整示例

    import matplotlib.pyplot as plt
    import numpy as np; np.random.seed(42)
    
    t = np.linspace(0,3,14)
    y = np.random.rand(len(t))
    
    plt.plot(t,y,'-gD',markevery = np.where(y > 0.5, True, False))
    # or 
    #plt.plot(t,y,'-gD',markevery = np.arange(len(t))[y > 0.5])
    
    plt.xlabel('t (s)')
    plt.ylabel('y')
    
    plt.show()
    

    导致

    【讨论】:

    • markevery = np.where(y > 0.5, True, False) throws ValueError: 具有多个元素的数组的真值是不明确的。使用 a.any() 或 a.all()。使用markevery = list(np.where(y > 0.5, True, False)) 可以解决问题。
    • 显然markevery = np.arange(len(t))[y > 0.5] 抛出了完全相同的错误。但是将输出作为list 传递可以解决问题。这些错误在 Matplotlib 3.1.3 中抛出。自 2017 年首次发布此问题以来,可能发生了重大变化。
    • @pfabri 感谢您的通知。这确实在很久以前就出错了。我现在在github.com/matplotlib/matplotlib/pull/17276 中修复了它。
    • 不客气。我尝试编辑您的答案,在我的评论中添加修复作为替代方案,但编辑队列已满。也许您也可以尝试...如果您发现我的评论有用...您知道,我渴望获得这些代表点:)
    【解决方案2】:

    markevery 使用布尔值来标记布尔值为真的每个点

    所以而不是markers_on = [x for x in y if abs(x)>0.5]

    你会做markers_on = [abs(x)>0.5 for x in y] 这将返回一个布尔值列表,其大小与 y 相同,每个点 |x| > 0.5 你会得到 True

    然后您将按原样使用您的代码:

    pl.plot(t,y,'-gD',markevery = markers_on)
    pl.title('Damped Sine Wave with %.1f Hz frequency' % f)
    pl.xlabel('t (s)')
    pl.ylabel('y')
    pl.grid()
    pl.show()
    

    我知道这个问题很老,但是我在尝试做最佳答案时找到了这个解决方案,因为我不熟悉 numpy,而且它似乎使事情过于复杂

    【讨论】:

      【解决方案3】:

      markevery 参数仅将 None、整数或布尔数组类型的索引作为输入。由于我是直接传递值,所以它抛出了错误。

      我知道它不是很pythonic,但我使用下面的代码来提出索引。

      marker_indices = []
      for x in range(len(y)):
          if abs(y[x]) > 0.5:
              marker_indices.append(x)
      

      【讨论】:

        【解决方案4】:

        我遇到这个问题是因为我试图标记一些超出数据框范围的点。

        例如:

        some_df.shape
        -> (276, 9)
        
        markers = [1000, 1080, 1120]
        
        some_df.plot(
            x='date',
            y=['speed'],
            figsize=(17, 7), title="Performance",
            legend=True,
            marker='o',
            markersize=10,
            markevery=markers,
        )
        
        -> ValueError: markevery=[1000, 1080, 1120] is iterable but not a valid numpy fancy index
        

        只需确保您作为标记提供的值在您要绘制的数据框的范围内。

        【讨论】:

          猜你喜欢
          • 2016-11-25
          • 2016-08-17
          • 1970-01-01
          • 2020-07-31
          • 2017-05-20
          • 1970-01-01
          • 2021-11-30
          • 2017-03-03
          • 1970-01-01
          相关资源
          最近更新 更多