通过另一个数组中的值阈值快速计数 numpy 数组的元素

C8H*_*4O2 7 python numpy cumulative-frequency

给定一numpy组阈值,生成满足这些值的另一个数组的计数数组的最有效方法是什么?

假设阈值数组较小且已排序,并且要计数的值数组较大且未排序。

示例:对于 的每个元素,计算大于或等于它valueLevels的元素:values

import numpy as np

n = int(1e5) # size of example

# example levels: the sequence 0, 1., 2.5, 5., 7.5, 10, 5, ... 50000, 75000
valueLevels =  np.concatenate(
                   [np.array([0.]), 
                    np.concatenate([ [ x*10**y for x in [1., 2.5, 5., 7.5] ] 
                                   for y in range(5) ] ) 
                    ]
                )

np.random.seed(123)
values = np.random.uniform(low=0, high=1e5, size=n)
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已经尝试过列表理解方法。

  • np.array([sum(values>=x) for x in valueLevels])速度慢得令人难以接受
  • np.array([len(values[values>=x]) for x in valueLevels])是一个进步
  • 排序values确实加快了理解速度(在示例中,从约 7 毫秒到 0.5 毫秒),但排序的成本(约 8 毫秒)超过了一次性使用节省的成本

我现在最好的就是对这种方法的理解:

%%timeit 
np.array([np.count_nonzero(values>=x) for x in valueLevels])
# 1000 loops, best of 3: 1.26 ms per loop
Run Code Online (Sandbox Code Playgroud)

这对于我的目的来说是可以接受的,但出于好奇,

我想知道的

  • 如果列表理解是可行的方法,它可以加快吗?或者,
  • 其他方法更快吗?(我有一种模糊的感觉,这可以通过在阈值数组上广播值数组来完成,但我不知道如何获得正确的尺寸np.broadcast_arrays()

Tim*_*chs 5

到目前为止我最快的是

\n\n
%timeit count_nonzero(values >= atleast_2d(valueLevels).T, axis=1)\n# 1000 loops, best of 3: 860 \xc2\xb5s per loop\n
Run Code Online (Sandbox Code Playgroud)\n\n

sum速度较慢:

\n\n
%timeit sum(values >= atleast_2d(valueLevels).T, axis=1)\n# 100 loops, best of 3: 2.5 ms per loop\n
Run Code Online (Sandbox Code Playgroud)\n\n

@Divakar 的版本甚至更慢:

\n\n
%timeit count_nonzero(values[:, None] >= valueLevels, axis=1)\n# 100 loops, best of 3: 3.86 ms per loop\n
Run Code Online (Sandbox Code Playgroud)\n\n

但是,我可能仍然会使用您的列表理解,它不会慢很多,并且不会创建一个大的 2D 布尔数组作为中间步骤:

\n\n
%timeit np.array([np.count_nonzero(values>=x) for x in valueLevels])\n# 1000 loops, best of 3: 987 \xc2\xb5s per loop\n
Run Code Online (Sandbox Code Playgroud)\n