numpy 计算多个大文件的百分比,而不将它们全部保存在内存中(Python)

ergxz8rk  于 2023-03-30  发布在  Python
关注(0)|答案(1)|浏览(133)

我想计算MERRA 2中某个值的第99个百分位数,气候再分析数据集。我有43年来每小时的观测数据,分布在361 x576点的Lat-lon网格上(1980-2022).目前我有我的计算值(源自obs.),以便于访问-每个文件包含大小为8760 x 361 x 576的np数组。
有没有一种方法可以迭代地计算第99个百分位数,方法是每年一个接一个地加载,并丢弃一些以前的数据,以保持所需的内存有限?我读了一些关于算法的阅读,但还没有找到任何适合我需要的东西。
如果我循环遍历每个纬度/经度对,我可以通过阅读并将每个年份的数据附加到数组中,然后使用np. percentile来计算每个点的整个时间序列的第99个百分位数。然而,这需要每个点大约5分钟,并且对于大约200 k个点,这将花费太长的时间。我正在寻找更快/更有效的东西。即使是一个可靠的近似值也可以。
先谢了!

oo7oh9g9

oo7oh9g91#

根据Stef的观察,我们只需要跟踪前1%,但我用NumPy数组和分区来做到这一点:

import numpy as np

# Simulated files (3x5 grid instead of 361x576)
def files():
    np.random.seed(123)
    for year in range(43):
        yield np.random.random((8760, 3, 5))

# Just for testing; Compute expectation with np.percentile
def reference(files):
    whole = np.vstack(files)
    return np.percentile(whole, 99, 0, method='closest_observation')

# The actual solution
def solution(files):

    # Preparation for getting top 1% = top k
    k = round(43 * 8760 / 100)
    def top_k(a):
        return np.partition(a, ~k, 0)[~k:]

    # Compute the result
    result = top_k(next(files))
    for other in files:
        other = top_k(other)
        both = np.vstack((result, other))
        result = top_k(both)
    return result[0]

expect = reference(files())
result = solution(files())

print('expect:')
print(expect)

print('\nresult:')
print(result)

print('\ndifference:')
print(result - expect)

输出(Attempt This Online!):

expect:
[[0.98989099 0.98997275 0.99009619 0.98969514 0.99034828]
 [0.9898165  0.99010689 0.98995486 0.99006558 0.98968308]
 [0.98996179 0.98979965 0.9896849  0.98996829 0.99012452]]

result:
[[0.98989099 0.98997275 0.99009619 0.98969514 0.99034828]
 [0.9898165  0.99010689 0.98995486 0.99006558 0.98968308]
 [0.98996179 0.98979965 0.9896849  0.98996829 0.99012452]]

difference:
[[0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]]

使用模拟的36x58网格,在ATO网站上,“计算结果”部分花费了不到30秒。因此,对于您自己的计算机上的真实的数据,它应该花费不到一个小时。

相关问题