python - 在 numpy 数组中对 1 的 block 进行排名的快速、python 风格的方法?

标签 python arrays numpy list-comprehension

我有一个由 01 组成的 numpy 数组。数组中的每个 1 序列代表一个事件的发生。我想用特定于事件的 ID 号标记与事件对应的元素(以及带有 np.nan 的其余数组元素)我当然可以在循环中这样做,但是是否有更多的“python- ish”(快速,矢量化)的方式?

我要标记的具有 3 个事件的 numpy 数组示例。

import numpy as np 
arr = np.array([0,0,0,1,1,1,0,0,0,1,1,0,0,0,1,1,1,1])
some_func(arr)

# Expected output of some_func I search for: 
# [np.nan,np.nan,np.nan,0,0,0,np.nan,np.nan,np.nan,1,1,np.nan,np.nan,np.nan,2,2,2,2]

最佳答案

你想要标记,幸运的是,有一个带有 SciPy 的,scipy.ndimage.label -

In [43]: from scipy.ndimage import label

In [47]: out = label(arr)[0]

In [48]: np.where(arr==0,np.nan,out-1)
Out[48]: 
array([nan, nan, nan,  0.,  0.,  0., nan, nan, nan,  1.,  1., nan, nan,
       nan,  2.,  2.,  2.,  2.])

另一个有一些 NumPy 工作 -

def rank_chunks(arr):
    m = np.r_[False,arr.astype(bool)]
    idx = np.flatnonzero(m[:-1] < m[1:])
    id_ar = np.zeros(len(arr),dtype=float)
    id_ar[idx[1:]] = 1
    out = id_ar.cumsum()
    out[arr==0] = np.nan
    return out

另一个带有masking + np.repeat -

def rank_chunks_v2(arr):
    m = np.r_[False,arr.astype(bool),False]
    idx = np.flatnonzero(m[:-1] != m[1:])
    l = idx[1::2]-idx[::2]
    out = np.full(len(arr),np.nan,dtype=float)
    out[arr!=0] = np.repeat(np.arange(len(l)),l)
    return out

计时(将给定输入平铺到 1Mx)-

In [153]: arr_big = np.tile(arr,1000000)

In [154]: %timeit np.where(arr_big==0,np.nan,label(arr_big)[0]-1)
     ...: %timeit rank_chunks(arr_big)
     ...: %timeit rank_chunks_v2(arr_big)
1 loop, best of 3: 312 ms per loop
1 loop, best of 3: 263 ms per loop
1 loop, best of 3: 229 ms per loop

关于python - 在 numpy 数组中对 1 的 block 进行排名的快速、python 风格的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57573350/

相关文章:

python - 为什么 Django 称我的 datetimes 天真而他们不是?

python - 通过 TCP/UDP 发送一个大数据包和许多小数据包?

Python:更改 pip 路径

java - 使用数组复制的数组存储异常

Java:数组如何提供即时查找

javascript - 为什么下划线的差异只能以一种方式起作用

python - 将 numpy 数组转换为 C 连续顺序的最便宜方法?

python - 如何将这个迭代函数写成递归函数?

python - 处理零乘以 NaN

python - 用其他数组给定的索引屏蔽一个数组