Python 矢量化,如何使用 numpy 获取每一行的所有索引

Python vectorization, how to get all index for every row with numpy

我很难解决这个问题,主要问题是我是 运行 一个模拟,所以对于 lops 主要是被禁止的,我有一个 NxN 的 numpy 数组,在这种情况下我的大约是 (10000x20)。

stoploss = 19.9 # condition to apply
monte_carlo_simulation(20,1.08,10000,20) #which gives me that 10000x20 np array
mask_trues = np.where(np.any((simulation <= stoploss) == True, axis=1)) # boolean mask

我需要一些代码来制作一个新的 len(10000) 向量,其中 returns 一个包含每一行所有位置的数组,让我们假设:

function([[False,True,True],[False,False,True]])
output = [[1,2],[2]]

同样,主要问题在于没有使用循环。

这是使用 np.split()np.diff() 的一种方法:

x, y = np.where(boolean_array)
np.split(y, np.where(np.diff(x) != 0)[0] + 1)

演示:

In [12]: a = np.array([[False,True,True],[False,False,True]])

In [13]: x, y = np.where(a)

In [14]: np.split(y, np.where(np.diff(x) != 0)[0] + 1)
Out[14]: [array([1, 2]), array([2])]

就是这样:

list(map(np.where, my_array))

与 Kasrâmvd 解决方案的性能比较:

def f(a):
    return list(map(np.where, a))

def g(a):
    x, y = np.where(a)
    return np.split(y, np.where(np.diff(x) != 0)[0] + 1)

a = np.random.randint(2, size=(10000,20))

%timeit f(a)
%timeit g(a)


7.66 ms ± 38.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
13.3 ms ± 188 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

为了完整起见,我将演示一种稀疏矩阵方法:

In [57]: A = np.array([[False,True,True],[False,False,True]])
In [58]: A
Out[58]: 
array([[False,  True,  True],
       [False, False,  True]])
In [59]: M = sparse.lil_matrix(A)
In [60]: M
Out[60]: 
<2x3 sparse matrix of type '<class 'numpy.bool_'>'
    with 3 stored elements in LInked List format>
In [61]: M.data
Out[61]: array([list([True, True]), list([True])], dtype=object)
In [62]: M.rows
Out[62]: array([list([1, 2]), list([2])], dtype=object)

并制作一个大的稀疏的:

In [63]: BM = sparse.random(10000,20,.05, 'lil')
In [64]: BM
Out[64]: 
<10000x20 sparse matrix of type '<class 'numpy.float64'>'
    with 10000 stored elements in LInked List format>
In [65]: BM.rows
Out[65]: 
array([list([3]), list([]), list([6, 15]), ..., list([]), list([11]),
       list([])], dtype=object)

粗略时间测试:

In [66]: arr = BM.A
In [67]: timeit sparse.lil_matrix(arr)
19.5 ms ± 421 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [68]: timeit list(map(np.where,arr))
11 ms ± 55.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [69]: %%timeit
    ...: x,y = np.where(arr)
    ...: np.split(y, np.where(np.diff(x) != 0)[0] + 1)
    ...: 
13.8 ms ± 24.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

生成 csr 稀疏格式矩阵更快:

In [70]: timeit sparse.csr_matrix(arr)
2.68 ms ± 120 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [71]: Mr = sparse.csr_matrix(arr)
In [72]: Mr.indices
Out[72]: array([ 3,  6, 15, ...,  8, 16, 11], dtype=int32)
In [73]: Mr.indptr
Out[73]: array([    0,     1,     1, ...,  9999, 10000, 10000], dtype=int32)
In [74]: np.where(arr)[1]
Out[74]: array([ 3,  6, 15, ...,  8, 16, 11])

它的 indices 就像列 where,而 indptr 就像 split indices.