numpy-使用先前的值进行数组加法

时间:2018-10-15 16:04:20

标签: python arrays numpy

这是我编写代码的方式,其中“分钟”和“差事”是相同大小的列表(下面的示例)。

但是这些是两个numpy数组,因此此代码不起作用。另一件事是我希望结果“ done”也成为一个numpy数组。

done = 0
for i in minute:
    if done < minute:
        done = minute + (errands * 2)
    else:
        done = done + (errands * 2)
    print (done)

因此,我也尝试使用“ np.where”

import numpy as np
done = 0
done = np.where(done < minute, minute + (errands * 2), done + (errands * 2))
print(done)

这将是完美的,但是这里的问题是它不会持续更新“ done”,因此在某些时候将运行“ done = done +(errands * 2)”的等效代码(如果有意义) )。

一些numpy数组的小例子:

minute = np.array([2, 2, 5, 5, 6, 7, 9, 11, 15])

errands = np.array([1, 1, 1, 7, 2, 2, 1, 1, 1])

为了让我尽可能清楚,我希望“完成”的输出是

done = np.array([4, 6, 8, 22, 26, 30, 32, 34, 36])

预先感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

由于更新,这是一个迭代问题。但是,它是O(n),可以使用numbanjit高效地完成:

设置

from numba import njit

您可能必须pip install numba


@njit
def toggle(a, b):
    done, out = 0, []    
    for i in range(len(a)):
        if done < a[i]:
            done = a[i] + (b[i] * 2)
        else:
            done = done + (b[i] * 2)
        out.append(done)
    return np.array(out)

toggle(minute, errands)

array([ 4,  6,  8, 22, 26, 30, 32, 34, 36], dtype=int64)

性能

minute = np.repeat(minute, 10000)
errands = np.repeat(errands, 10000)

%timeit toggle(minute, errands)
2.02 ms ± 9.84 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit toggle_no_njit(minute, errands)
64.4 ms ± 738 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

答案 1 :(得分:1)

这可以单独使用numpy来完成:

def smart(m, e):
    e = 2*e
    r = np.empty(e.size+1, e.dtype)
    r[0] = 0
    e.cumsum(out=r[1:])
    return r[1:] + np.maximum.accumulate(m - r[:-1])

测试和计时: 设置大小为1000的随机问题:

>>> e = np.random.uniform(1, 3, 1000)
>>> m = np.random.uniform(1, 7, 1000).cumsum()

给出与numba相同的结果:

>>> np.allclose(toggle(m, e), smart(m, e))
True

但是即使不包括编译时间,速度也要快得多:

>>> timeit(lambda: toggle(m, e))
21.466296120896004
>>> timeit(lambda: smart(m, e))
11.608282678993419

答案 2 :(得分:0)

您可以使用Numba非常有效地完成此任务。

但是请避免使用列表,就像@ user3483203在回答中所做的那样。由于Numba无法直接处理列表2.6.2.4.1. List Reflection

,因此列表的开销非常高

示例

@nb.njit
def toggle_2(a, b):
    done=0.
    out=np.empty(a.shape[0],dtype=a.dtype)

    for i in range(a.shape[0]):
        if done < a[i]:
            done = a[i] + (b[i] * 2)
        else:
            done = done + (b[i] * 2)
        out[i]=done
    return out

性能

e = np.random.uniform(1, 3, 1_000)
m = np.random.uniform(1, 7, 1_000).cumsum()

Paul Panzer (smart) : 13.22 µs
user3483203 (toggle): 18.47 µs
toggle_2              2.47  µs

e = np.random.uniform(1, 3, 1_000_000)
m = np.random.uniform(1, 7, 1_000_000).cumsum()

Paul Panzer (smart) : 15.97 ms
user3483203 (toggle): 30.28 ms
toggle_2              3.77  ms