Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.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_Algorithm_Performance_Numpy_Scipy - Fatal编程技术网

Python/Numpy查找长度变量跨度

Python/Numpy查找长度变量跨度,python,algorithm,performance,numpy,scipy,Python,Algorithm,Performance,Numpy,Scipy,考虑形状(n,)单调递增的numpy数组 我的问题是有效地提取每个span(i,j),以便: X[i:j].sum() >= v and X[i:j-1].sum() < v 其中: list(variable_length_spans(X,10)) [(0, 3), (1, 3), (2, 4), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)] 这必须是一种更有效/更优雅的方式。然而,我可以找到方法。如有任何建议,我们将不胜感激

考虑形状
(n,)
单调递增的numpy数组

我的问题是有效地提取每个span
(i,j)
,以便:

X[i:j].sum() >= v and X[i:j-1].sum() < v
其中:

list(variable_length_spans(X,10))
[(0, 3), (1, 3), (2, 4), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)]
这必须是一种更有效/更优雅的方式。然而,我可以找到方法。如有任何建议,我们将不胜感激

F

更新#1:时间安排 使用20K随机元素(10次运行的平均结果):

  • 可变长度跨度:0.009332秒
  • 戴维斯跨度:0.009259秒
  • 广播时间:1.896222秒
使用1M个随机元素(50次运行的平均结果):

  • 可变长度跨度:0.528101
  • 戴维斯大学广播:0.534576秒

目前这是一个二次算法,可以在线性时间内完成,如下所示:

def spans(X, v):
    n, = X.shape
    i = 0
    total = 0
    for j in xrange(0, n):
        total += X[j]
        while total >= v:
            yield (i, j+1)
            total -= X[i]
            i += 1

基于小波变换的矢量化方法-

样本输入、输出-

In [212]: X
Out[212]: array([  2,   3,   7,  19, 110, 112, 120, 140, 161])

In [213]: v
Out[213]: 10

In [214]: out
Out[214]: 
array([[0, 3],
       [1, 3],
       [2, 4],
       [3, 4],
       [4, 5],
       [5, 6],
       [6, 7],
       [7, 8],
       [8, 9]])

错别字,对不起,我指的是X而不是dt。没有返回,因为变量_length_span是一个生成器(注意yield语句)。感谢您的编辑!那么,问题中列出的循环代码真的可以实现伪代码:
X[j]-X[i]>=v和X[j-1]-X[i]
?这个循环代码有很多求和,我在伪代码中没有看到。啊,对了,谢谢你的澄清。这个形状不是
(n,1)
;这是一个一维数组。据我所知,你的版本和我的版本具有相同的复杂性(多亏了我在内部for循环中使用的break语句)。我说得对吗?最坏的情况下不是。例如,假设n=100,X=[1,1,1,…,100000000]。然后你的解决方案需要大约n(n-1)/2次循环迭代,而我的解决方案需要大约2n次循环迭代。好的,明白了,这比我的解决方案要好。然而,两者的运行时间都非常相同。是否存在更好的解决方案?它们的运行时间不同。与二次型相比,线性型是一个显著的改进。解决方案非常优雅,但是如果X增长,diff=cumsums[:,None]-cumsums可能会耗尽我的内存。@FrançoisKawala是的,它具有向量化的固有性质,需要足够的内存一次性完成任务。你的X有多大?我的X大约是1e5。我对我们的方法进行了计时(timeit),似乎嵌套循环更快。(10倍平均值,X.shape==(1e4,))可变长度跨度:0.004613/广播跨度:0.456812。这有意义吗?@FrançoisKawala是的,如果输入数据在求和的早期就被破坏了,那么向量化方法就不会有什么好处。有了这个矢量化的解决方案,我们创建了所有的求和和和跨度(微分),然后一次检查,但遗憾的是没有从您的案例中受益。好吧,很高兴知道!我天真地认为,我对for循环所做的一切都会比向量化方法慢。我已经根据我的数据绘制了随机值进行了测试,因此我想我会坚持使用迭代方法进行测试。
def spans(X, v):
    n, = X.shape
    i = 0
    total = 0
    for j in xrange(0, n):
        total += X[j]
        while total >= v:
            yield (i, j+1)
            total -= X[i]
            i += 1
# Get cumulative summations
cumsums = X.cumsum()

# Elementwise subtractions between cumsums & its one place shifted version
diffs = cumsums[:,None] - np.append(0,cumsums[:-1])

# Detect cumulative summation span check
mask = diffs >= v

# Get valid mask for later selection purpose
valid = mask.any(0)

# Get first trigger indices
max_idx = np.argmax(mask,0)+1

# Concatenate row indices alongwith trigger ones for final output
out = np.column_stack((np.arange(max_idx.size),max_idx))[valid]
In [212]: X
Out[212]: array([  2,   3,   7,  19, 110, 112, 120, 140, 161])

In [213]: v
Out[213]: 10

In [214]: out
Out[214]: 
array([[0, 3],
       [1, 3],
       [2, 4],
       [3, 4],
       [4, 5],
       [5, 6],
       [6, 7],
       [7, 8],
       [8, 9]])