numpy Python在没有完整数组的实时流中查找min和max

inn6fuwd  于 12个月前  发布在  Python
关注(0)|答案(3)|浏览(120)

我有一个连续的值流,数百万条记录。我需要找到最小值和最大值,因为数字不断进入。整个数据数组不可用。到达的数据没有存储。最小最大范围也是未知的。
我试过类似的方法,但效果不太好。有没有更好的方法来解决这些问题,使用库,numpyscipy

import numpy as np
rng = np.random.default_rng()

test = rng.choice(np.arange(-100,100, dtype=int), 10, replace=False)
testmax = 0
testmin = 0
for i in test: #simulates a stream
    if i < testmax:
        testmin = i
    if i > testmax:
        testmax = i
    if i < testmin:
        testmin = i

print (test, 'min: ',testmin, 'max: ', testmax)

>>> print (test, 'min: ',testmin, 'max: ', testmax)
[ 39 -32  61 -18 -53 -57 -69  98 -88 -47] min:  -47 max:  98 #should be -88 and 98
>>>
>>> print (test, 'min: ',testmin, 'max: ', testmax)
[-65 -53   1   2  26 -62  82  70  39 -44] min:  -44 max:  82 #should be -65 and 82
>>>

字符串

2g32fytz

2g32fytz1#

这个错误(打字错误)在注解中已经指出了,但是你只需要两个比较--这可以使用三元运算符来完成。你还应该将max初始化为负无穷大,将min初始化为正无穷大。这有助于避免这样的情况,例如,你将min设置为0,但是流中实际看到的最小数字大于0。

import numpy as np

rng = np.random.default_rng(42)

stream_min = -100
stream_max = 100
test = rng.choice(np.arange(stream_min, stream_max+1, dtype=int),
                  10,
                  replace=False)

testmax = -float("inf")
testmin = float("inf")

# simulates a stream
for i in test:
    testmax = i if i > testmax else testmax
    testmin = i if i < testmin else testmin

print (test, "min: ", testmin, "max: ", testmax)
# [ 97  49 -83  26 -15 -16  38 -82 -60  69] min:  -83 max:  97

字符串
为什么三进制运算符超过使用min/max?好吧,它更快。

stream_min = -1000
stream_max = 1000
test = rng.choice(np.arange(stream_min, stream_max+1, dtype=int),
                  500,
                  replace=False)

def ternary():
    testmax = -float("inf")
    testmin = float("inf")

    for i in test:
        testmax = i if i > testmax else testmax
        testmin = i if i < testmin else testmin

    return testmin, testmax

def plainif():
    testmax = -float("inf")
    testmin = float("inf")

    for i in test:
        if i > testmax:
            testmax = i
        if i < testmin:
            testmin = i

    return testmin, testmax

def minmax():
    testmax = -float("inf")
    testmin = float("inf")

    for i in test:
        testmax = max(i, testmax)
        testmin = min(i, testmax)

    return testmin, testmax

%timeit ternary() 
55.4 µs ± 3.26 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit plainif()
50.6 µs ± 2.23 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit minmax()
170 µs ± 6.01 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)


使用if语句和三元运算符几乎是等价的(if快一点)。

62o28rlo

62o28rlo2#

请注意,Python方便地提供了math.inf-math.inf,它们是保证比任何可能的整数都大或小的浮点数。所以只需写:

testmax = -math.inf
testmin = math.inf
for value in ...:
    testmax = max(testmax, value)
    testmin = min(testmin, value)

字符串

jobtbby3

jobtbby33#

一个有趣的itertools版本,如果有人 * 实际上 * 想要实时的最小/最大值,而不仅仅是最终的:

from itertools import tee, accumulate

test = 1, -2, 3, -4, 5, -6

for testmin, testmax in zip(*map(accumulate, tee(test), (min, max))):
    print(testmin, testmax)

字符串
输出(Attempt This Online!):
另一个解决方案,阅读1000块:

from random import random
from itertools import islice

test = [random() for _ in range(10**6)]

testmin = float('inf')
testmax = float('-inf')
it = iter(test)
while chunk := list(islice(it, 1000)):
    testmin = min(testmin, min(chunk))
    testmax = max(testmax, max(chunk))

print(testmin, testmax)


Attempt This Online!

相关问题