Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 检查numpy数组窗口中的元素是否有限的更快方法_Python_Arrays_Performance_Numpy - Fatal编程技术网

Python 检查numpy数组窗口中的元素是否有限的更快方法

Python 检查numpy数组窗口中的元素是否有限的更快方法,python,arrays,performance,numpy,Python,Arrays,Performance,Numpy,我有一个非常长的NumPy数组,其中包含1\u 000\u 000元素,我想在数组中滑动50元素窗口,询问窗口中的所有元素是否都是有限的。如果50元素窗口中的所有元素都是有限的,则返回True(对于该窗口),否则,如果50元素窗口中的一个或多个元素不是有限的,则返回False(对于该窗口)。继续此评估,直到评估完所有窗口。一个很好的方法是: import numpy as np def rolling_window(a, window): a = np.asarray(a) s

我有一个非常长的NumPy数组,其中包含
1\u 000\u 000
元素,我想在数组中滑动
50
元素窗口,询问窗口中的所有元素是否都是有限的。如果
50
元素窗口中的所有元素都是有限的,则返回
True
(对于该窗口),否则,如果
50
元素窗口中的一个或多个元素不是有限的,则返回
False
(对于该窗口)。继续此评估,直到评估完所有窗口。一个很好的方法是:

import numpy as np

def rolling_window(a, window):
    a = np.asarray(a)
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)

    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

if __name__ == "__main__":
    a = np.random.rand(100_000_000)  # This is 10x shorter than my real data
    w = 50
    idx = np.random.randint(0, len(a), size=len(a)//10)  # Simulate having np.nan in my array
    a[idx] = np.nan
    print(np.all(rolling_window(np.isfinite(a), w), axis=1))
但是,当我的数组长度为
1\u 000\u 000
时,速度会很慢。是否有一种更快的方法可以完成这项任务,而不需要大量内存?

方法#1:将跨步窗口直接插入分配的
isfinite掩码中-

def strided_allfinite(a, w):
    m = np.isfinite(a)
    p = rolling_window(m, w)
    nmW = ~m[:w]
    if nmW.any():
        m[:np.flatnonzero(nmW).max()] = False
    p[~m[w-1:]] = False
    return m[:-w+1]
给定样本数据的计时:

In [323]: N = 100_000_000
     ...: w = 50
     ...: 
     ...: np.random.seed(0)
     ...: a = np.random.rand(N)  # This is 10x shorter than my real data
     ...: idx = np.random.randint(0, len(a), size=len(a)//10)  # Simulate...
     ...: a[idx] = np.nan

# Original soln
In [324]: %timeit np.all(rolling_window(np.isfinite(a), w), axis=1)
1.61 s ± 14.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [325]: %timeit strided_allfinite(a, w)
556 ms ± 87.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
方法#2

我们可以利用-

方法#3

与-


在我的测试中,
as_stried
的速度是
convolve
的两倍。我的咖啡用完了,无法理解
stried\u allfinite
背后的逻辑。但是
np.all(stripped\u allfinite(a,w)==np.all(滚动窗口(a,w,axis=1))
给了我
False
@QuangHoang这是检查相等性的错误方法。尝试
np.array\u equal(跨步有限(a,w),np.all(滚动窗口(np.isfinite(a,w),axis=1))
。可能还要咖啡吗?:)我不明白,这可能不是最好的方法,但肯定是正确的方法,因为两个数组都不包含nan。你能解释一下原因吗?@QuangHoang那么你应该做
np.all(跨步有限(a,w)==np.all(滚动窗口(np.isfinite(a,w),axis=1))
。现在,我需要咖啡。无限元素的频率/稀疏度是多少?如果它们是稀疏的,那么最好先获取更大的块,仅当存在无限元素时才细分它们
np.convolve(np.isfinite(a), np.ones(w),'valid')==w
from scipy.ndimage.morphology import binary_erosion

m = np.isfinite(a)
out = binary_erosion(m, np.ones(w, dtype=bool))[w//2:len(a)-w+1+w//2]