【问题标题】:Sliding standard deviation on a 1D NumPy array一维 NumPy 数组上的滑动标准差
【发布时间】:2017-04-07 23:35:10
【问题描述】:

假设你有一个数组并且想要创建另一个数组,它的值依次等于第一个数组的 10 个元素的标准差。在 for 循环的帮助下,它可以像下面的代码一样轻松编写。我想要做的是避免使用 for 循环来加快执行时间。有什么建议吗?

Code
a = np.arange(20)
b = np.empty(11)
for i in range(11):
    b[i] = np.std(a[i:i+10])

【问题讨论】:

    标签: python performance numpy iteration vectorization


    【解决方案1】:

    您可以使用np.lib.stride_tricks.as_strided 创建一个滑动窗口的二维数组,这将是给定1D 数组的视图,因此不会占用更多内存。然后,只需沿第二个轴 (axis=1) 使用 np.std 以矢量化方式获得最终结果,就像这样 -

    W = 10 # Window size
    nrows = a.size - W + 1
    n = a.strides[0]
    a2D = np.lib.stride_tricks.as_strided(a,shape=(nrows,W),strides=(n,n))
    out = np.std(a2D, axis=1)
    

    运行时测试

    函数定义-

    def original_app(a, W):
        b = np.empty(a.size-W+1)
        for i in range(b.size):
            b[i] = np.std(a[i:i+W])
        return b
        
    def vectorized_app(a, W):
        nrows = a.size - W + 1
        n = a.strides[0]
        a2D = np.lib.stride_tricks.as_strided(a,shape=(nrows,W),strides=(n,n))
        return np.std(a2D,1)
    

    时间和验证 -

    In [460]: # Inputs
         ...: a = np.arange(10000)
         ...: W = 10
         ...: 
    
    In [461]: np.allclose(original_app(a, W), vectorized_app(a, W))
    Out[461]: True
    
    In [462]: %timeit original_app(a, W)
    1 loops, best of 3: 522 ms per loop
    
    In [463]: %timeit vectorized_app(a, W)
    1000 loops, best of 3: 1.33 ms per loop
    

    所以,大约 400x 加速了!

    为了完整起见,这里是等效的 pandas 版本 -

    import pandas as pd
    
    def pdroll(a, W): # a is 1D ndarray and W is window-size
        return pd.Series(a).rolling(W).std(ddof=0).values[W-1:]
    

    【讨论】:

    • 这有点复杂,但更快的解决方案。谢谢!
    【解决方案2】:

    不是很花哨,但是没有循环的代码会是这样的:

    a = np.arange(20)
    b = [a[i:i+10].std() for i in range(len(a)-10)]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-28
      • 1970-01-01
      • 1970-01-01
      • 2019-09-11
      • 2022-11-01
      • 2011-01-25
      • 1970-01-01
      相关资源
      最近更新 更多