【问题标题】:Finding local maxima of xy data point graph with numpy?用numpy查找xy数据点图的局部最大值?
【发布时间】:2015-11-29 02:20:21
【问题描述】:

我想在包含数千个值的巨大数据点集中找到最有效的方法。作为输入,使用了两个带有 x 和 y 值的长列表。

考虑这个简单的例子:

xval = [-0.15, -0.02, 0.1, 0.22, 0.36, 0.43, 0.58, 0.67, 0.79, 0.86, 0.96 ]

yval = [-0.09, 0.13, -0.01, -0.1, -0.05, 0.2, 0.56, 0.47, 0.35, 0.43, 0.69]

所需的输出是带有峰值点索引的列表,这里 locMaxId =[1,6,10]。 比较最近的邻居是解决方案,但对于 10k 值?

【问题讨论】:

    标签: python numpy max points


    【解决方案1】:

    您可以让 numpy 处理迭代,即对其进行矢量化:

    def local_maxima(xval, yval):
        xval = np.asarray(xval)
        yval = np.asarray(yval)
    
        sort_idx = np.argsort(xval)
        yval = yval[sort_idx]
        gradient = np.diff(yval)
        maxima = np.diff((gradient > 0).view(np.int8))
        return np.concatenate((([0],) if gradient[0] < 0 else ()) +
                              (np.where(maxima == -1)[0] + 1,) +
                              (([len(yval)-1],) if gradient[-1] > 0 else ()))
    

    EDIT 所以代码首先计算从每个点到下一个点的变化(gradient)。下一步有点棘手...如果您执行np.diff((gradient &gt; 0),则生成的布尔数组为True,其中从增长(&gt; 0)变为不增长(&lt;= 0)。通过将其设置为与布尔数组大小相同的有符号整数,您可以区分从增长到不增长 (-1) 到相反 (+1) 的转换。通过采用与布尔数组具有相同 dtype 大小的有符号整数类型的.view(np.int8),我们避免了复制数据,如果我们执行不那么 hacky 的.astype(int) 就会发生这种情况。剩下的就是处理第一个和最后一个点,并将所有点连接到一个数组中。我今天发现的一件事是,如果您在发送到np.concatenate 的元组中包含一个空列表,它会作为 dtype np.float 的空数组出现,最终成为结果的 dtype,因此上述代码中空元组的更复杂的串联。

    有效:

    In [2]: local_maxima(xval, yval)
    Out[2]: array([ 1,  6, 10], dtype=int64)
    

    而且相当快:

    In [3]: xval = np.random.rand(10000)
    
    In [4]: yval = np.random.rand(10000)
    
    In [5]: local_maxima(xval, yval)
    Out[5]: array([   0,    2,    4, ..., 9991, 9995, 9998], dtype=int64)
    
    In [6]: %timeit local_maxima(xval, yval)
    1000 loops, best of 3: 1.16 ms per loop
    

    此外,大部分时间是将数据从列表转换为数组并对其进行排序。如果您的数据已经排序并保存在数组中,您可能可以将性能提高 5 倍。

    【讨论】:

    • 是的,这正是我一直在寻找的!也许您可以为没有经验的用户添加一些 cmets:)
    • @ptaeck 看看这是否有意义,我经常用 Python 比用英语更好地解释自己...
    • 是的,现在好多了!如果你愿意,this one 有点难。
    猜你喜欢
    • 2016-05-18
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 1970-01-01
    • 2017-04-02
    • 2014-05-15
    • 1970-01-01
    相关资源
    最近更新 更多