我有一个numpy数组:
a = [3., 0., 4., 2., 0., 0., 0.]
我希望创建一个新的数组,使其中非零元素转换为0,并将零元素转换为一个数字,该数字等于连续零元素的数量,即:
b = [0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 3.]
寻找矢量化的方法来处理此操作,因为数组将具有超过100万个元素。 非常感谢任何帮助。
我有一个numpy数组:
a = [3., 0., 4., 2., 0., 0., 0.]
我希望创建一个新的数组,使其中非零元素转换为0,并将零元素转换为一个数字,该数字等于连续零元素的数量,即:
b = [0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 3.]
寻找矢量化的方法来处理此操作,因为数组将具有超过100万个元素。 非常感谢任何帮助。
这应该会起到作用,大致上的实现方式是:1)找到所有连续的零并计数;2)计算输出数组的大小并初始化为零;3)将第一部分的计数放置在正确的位置。
def cz(a):
a = np.asarray(a, int)
# Find where sequences of zeros start and end
wz = np.zeros(len(a) + 2, dtype=bool)
wz[1:-1] = a == 0
change = wz[1:] != wz[:-1]
edges = np.where(change)[0]
# Take the difference to get the number of zeros in each sequence
consecutive_zeros = edges[1::2] - edges[::2]
# Figure out where to put consecutive_zeros
idx = a.cumsum()
n = idx[-1] if len(idx) > 0 else 0
idx = idx[edges[::2]]
idx += np.arange(len(idx))
# Create output array and populate with values for consecutive_zeros
out = np.zeros(len(consecutive_zeros) + n)
out[idx] = consecutive_zeros
return out
针对多样性的解决方案:
a = np.array([3., 0., 4., 2., 0., 0., 0.],dtype=np.int)
inds = np.cumsum(a)
#Find first occurrences and values thereof.
uvals,zero_pos = np.unique(inds,return_index=True)
zero_pos = np.hstack((zero_pos,a.shape[0]))+1
#Gets zero lengths
values = np.diff(zero_pos)-1
mask = (uvals!=0)
#Ignore where we have consecutive values
zero_inds = uvals[mask]
zero_inds += np.arange(zero_inds.shape[0])
#Create output array and apply zero values
out = np.zeros(inds[-1] + zero_inds.shape[0])
out[zero_inds] = values[mask]
out
[ 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 3.]
主要区别在于,只要数组单调递增,我们可以使用np.unique
查找数组的第一次出现。
a>300
),才能使这种方法变得更快。 - Daniel