【问题标题】:Numpy vectorization algorithms to sum up numbers with the same time stampsNumpy矢量化算法来总结具有相同时间戳的数字
【发布时间】:2011-11-03 23:06:45
【问题描述】:

我有两个数组P和T。P[i]是一个数字,其时间戳是T[i];可能有重复的时间戳。

我想产生另外两个数组Q和U,其中Q[i]有时间戳U[i],Q[i]是P中所有有时间戳U[i]的元素的总和;

例如,对于

P = [1, 2, 3, 4, 5] T = [0, 0, 1, 1, 1]

我会生产

Q = [3, 12] U = [0, 1];

在 numpy 中是否有一种快速的方法可以实现矢量化?

【问题讨论】:

    标签: python numpy vectorization


    【解决方案1】:

    使用 numpy 1.4 或更高版本:

    import numpy as np
    
    P = np.array([1, 2, 3, 4, 5]) 
    T = np.array([0, 0, 1, 1, 1])
    
    U,inverse = np.unique(T,return_inverse=True)
    Q = np.bincount(inverse,weights=P)
    print (Q, U)
    # (array([  3.,  12.]), array([0, 1]))
    

    请注意,这不是最快的解决方案。我是这样测试速度的:

    import numpy as np
    
    N = 1000
    P = np.repeat(np.array([1, 2, 3, 4, 5]),N)
    T = np.repeat(np.array([0, 0, 1, 1, 1]),N)
    
    def using_bincount():
        U,inverse = np.unique(T,return_inverse=True)
        Q = np.bincount(inverse,weights=P)
        return Q,U
        # (array([  3.,  12.]), array([0, 1]))
    
    def using_lc():
        U = list(set(T))
        Q = [sum([p for (p,t) in zip(P,T) if t == u]) for u in U]
        return Q,U
    
    def using_slice():
        U = np.unique(T)
        Q = np.array([P[T == u].sum() for u in U])
        return Q,U
    

    对于小型数组,wim's solution 更快(N=1):

    % python -mtimeit -s'import test' 'test.using_lc()'
    100000 loops, best of 3: 18.4 usec per loop
    % python -mtimeit -s'import test' 'test.using_slice()'
    10000 loops, best of 3: 66.8 usec per loop
    % python -mtimeit -s'import test' 'test.using_bincount()'
    10000 loops, best of 3: 52.8 usec per loop
    

    对于大型数组,joris's solution 更快(N=1000):

    % python -mtimeit -s'import test' 'test.using_lc()'
    100 loops, best of 3: 9.93 msec per loop
    % python -mtimeit -s'import test' 'test.using_slice()'
    1000 loops, best of 3: 390 usec per loop
    % python -mtimeit -s'import test' 'test.using_bincount()'
    1000 loops, best of 3: 846 usec per loop
    

    我怀疑在这种情况下是否重要,但基准测试可能会根据 numpy、python、OS 或硬件的版本而改变。在您的机器上重复这些基准测试不会有什么坏处。

    【讨论】:

      【解决方案2】:
      import numpy as np
      P = np.array([1, 2, 3, 4, 5]) 
      T = np.array([0, 0, 1, 1, 1])
      
      U = np.unique(T)
      Q = np.array([P[T == u].sum() for u in U])
      

      给予

      In [17]: print Q, U
      [3 12] [0 1]
      

      没有真正矢量化,但比列表解决方案更快。

      如果你想要更强大的这种分组功能,也许你可以看看pandas。

      【讨论】:

      • 非常好!虽然我会使用Q = np.array([P[T==u].sum() for u in U]) 来保持一致性。
      • 你如何衡量它比使用列表的解决方案更快?因为我得到了10000 loops, best of 3: 36.7 us per loop,比列表理解100000 loops, best of 3: 3 us per loop慢10倍。
      • 当我这么说的时候,我应该更多地解释它。我也做了一些 timeit 测试,但在更大的阵列上,你可以在 unutbu 的时间中看到,在这种情况下它更快。所以这取决于你要处理的数组。
      【解决方案3】:
      >>> P = [1, 2, 3, 4, 5]; T = [0, 0, 1, 1, 1]
      >>> U = list(set(T))
      >>> Q = [sum([p for (p,t) in zip(P,T) if t == u]) for u in U]
      >>> print Q, U
      [3, 12] [0, 1]
      

      【讨论】:

      • 不幸的是,我认为他不是在寻找标准的 lib 解决方案,因为他多次表示他正在寻找使用 numpy 数据结构的矢量化解决方案。
      • 问题中的示例有列表...但是对于 numpy 数组,使用 np.where 会更容易
      猜你喜欢
      • 2016-11-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-05
      • 1970-01-01
      • 2018-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多