如何在不使用循环的情况下仅从numpy数组中删除前导零?
import numpy as np
x = np.array([0,0,1,1,1,1,0,1,0,0])
# Desired output
array([1, 1, 1, 1, 0, 1, 0, 0])
我写了以下代码
x[min(min(np.where(x>=1))):]
我想知道是否有更有效的解决方案。
答案 0 :(得分:5)
您可以使用np.trim_zeros(x, 'f')
。
'f'表示从前面修剪零。 选项'b'将从后面修剪零。 默认选项'fb'从两侧修剪它们。
x = np.array([0,0,1,1,1,1,0,1,0,0])
# [0 0 1 1 1 1 0 1 0 0]
np.trim_zeros(x, 'f')
# [1 1 1 1 0 1 0 0]
答案 1 :(得分:2)
自np.trim_zeros
uses a for
loop以来,这是一个真正的矢量化解决方案:
x = x[np.where(x != 0)[0][0]:]
但是我不确定它在哪一点开始比np.trim_zeros
更有效率。在最坏的情况下(即具有大多数前导零的数组),它将更有效。
无论如何,它可以是一个有用的学习示例。
双面修剪:
>>> idx = np.where(x != 0)[0]
>>> x = x[idx[0]:1+idx[-1]]
答案 2 :(得分:1)
这是一种短路的numpy方法。它利用了0
对任何(?)dtype的表示为零字节的事实。
import numpy as np
import itertools
# check assumption that for example 0.0f is represented as 00 00 00 00
allowed_dtypes = set()
for dt in map(np.dtype, itertools.chain.from_iterable(np.sctypes.values())):
try:
if not np.any(np.zeros((1,), dtype=dt).view(bool)):
allowed_dtypes.add(dt)
except:
pass
def trim_fast(a):
assert a.dtype in allowed_dtypes
cut = a.view(bool).argmax() // a.dtype.itemsize
if a[cut] == 0:
return a[:0]
else:
return a[cut:]
与其他方法的比较:
生成情节的代码:
def np_where(a):
return a[np.where(a != 0)[0][0]:]
def np_trim_zeros(a):
return np.trim_zeros(a, 'f')
import perfplot
tf, nt, nw = trim_fast, np_trim_zeros, np_where
def trim_fast(A): return [tf(a) for a in A]
def np_trim_zeros(A): return [nt(a) for a in A]
def np_where(A): return [nw(a) for a in A]
perfplot.save('tz.png',
setup=lambda n: np.clip(np.random.uniform(-n, 1, (100, 20*n)), 0, None),
n_range=[2**k for k in range(2, 11)],
kernels=[
trim_fast,
np_where,
np_trim_zeros
],
logx=True,
logy=True,
xlabel='zeros per nonzero',
equality_check=None
)