【问题标题】:Find all the times in a (very large) array that have a difference greater than x在(非常大的)数组中查找差异大于 x 的所有时间
【发布时间】:2021-10-14 13:34:26
【问题描述】:

我的数组是时间,所以它是排序和递增的。

我必须拉出数组中差异大于 30 的开头/结尾。其他解决方案未涵盖的问题是数组有数千个值,因此遍历数组似乎效率低下。

hugeArr = np.array([0, 2.072, 50.0, 90.0, 91.1])

我想要的上述数组的输出类似于:(2.072,50) (50,90)。

有没有办法做到这一点?

【问题讨论】:

  • 这 30 个差异是否必须在连续值中?

标签: python arrays numpy tuples


【解决方案1】:

您可以使用np.diffnp.where 找到正确的索引:

>>> idxs = np.where(np.diff(hugeArr) > 30)[0]
>>> list(zip(hugeArr[idxs], hugeArr[idxs + 1]))
[(2.072, 50.0), (50.0, 90.0)]

(假设您只需要连续的值)

正如@not_speshal 所提到的,您可以使用np.column_stack 而不是list(zip(...)) 来保持在NumPy 范围内:

>>> np.column_stack((hugeArr[idxs], hugeArr[idxs+1]))
array([[ 2.072, 50.   ],
       [50.   , 90.   ]])

【讨论】:

  • 为了保持纯 numpy 解决方案,您可以将最后一行替换为 np.column_stack((hugeArr[idxs], hugeArr[idxs+1])) :)
  • 无论哪种方式都来自我+1。我也有同样的想法;)
  • @not_speshal 好点!添加到答案中。谢谢
  • 这非常有效。谢谢大家!
【解决方案2】:

试着想想你想要做什么。对于数组中的每个值,如果下一个值大于 30,您希望保存它们的元组。

这里的关键词是每个。这是一个经典的O(n) 复杂度算法,所以降低它的时间复杂度对我来说似乎是不可能的。

但是,您可以对您的数组进行特定的更改,以使算法更快。

例如,如果您正在寻找 30 的差值并且您知道平均差值为 1,那么您最好在 index i 处查找

difference = hugeArr[i+15] - hugeArr[i]

看看这是否大于 30。如果不是(而且可能不会),您可以跳过这 15 个索引,因为您知道两个连续值之间的差距不会大于大差距。

如果这对你有用,运行测试,15 是完全任意的,也许你的幻数是 25。稍微改变一下,看看你的函数运行需要多长时间。

【讨论】:

    【解决方案3】:

    想到的一个策略是,我们不必检查两个距离小于 30 的数字之间的数字,我们可以这样做,因为它已排序。例如,如果abs(hugeArr[0] - hugeArr[-1]) < 30 我们不需要检查任何东西,因为没有任何东西的距离会超过 30。

    我们将从尽头开始,向内努力。所以先检查起始编号和结束编号。然后我们走到一半hugeArr[len(hugeArr)//2] 并检查与hugeArr[0]hugeArr[-1] 的数字距离。然后我们进入范围(hugeArr[0:len(hugeArr)//2]hugeArr[len(hugeArr)//2:-1])。我们再次将这两个范围分成两半,并且无论端到端的距离小于 30,我们都不会检查这些范围。我们可以使它成为一个递归算法。

    在最坏的情况下,您到处都有超过 30 的距离并最终得到 O(n),但它可能会给您带来一些优势。

    类似这样的东西,但是您可能想重构为 numpy。

    def check(arr):
        pairs = []
        
        def check_range(hugeArr):
            difference = abs(hugeArr[0] - hugeArr[-1])
    
            if difference < 30:
                return
    
            if len(hugeArr) == 2:
                pairs.append((hugeArr[0], hugeArr[1]))
                return 
    
            halfway = len(hugeArr)//2
    
            check_range(hugeArr[:halfway+1])
            check_range(hugeArr[halfway:])
            
        check_range(arr)
        return pairs
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-04
      • 2016-09-18
      • 1970-01-01
      • 2020-08-20
      • 1970-01-01
      • 2016-11-17
      • 1970-01-01
      • 2011-09-30
      相关资源
      最近更新 更多