Python 基于值拆分Numpy数组

Python 基于值拆分Numpy数组,python,numpy,Python,Numpy,假设我有一个NumPy数组: a = np.array([0, 3, 5, 5, 0, 10, 14, 15, 56, 0, 12, 23, 45, 23, 12, 45, 0, 1, 0, 2, 3, 4, 0, 0 ,0]) 我想打印0之间的所有数字,并自动将它们添加到新的np.array(见下文): 是否有内置函数来执行此操作?您可以使用np获得零的索引。其中: zeros = np.where(a == 0)[0] 并在每对上迭代以分割数组: [a[i+

假设我有一个NumPy数组:

a = np.array([0, 3, 5, 5, 0, 10, 14, 15, 56, 0, 12, 23, 45, 23, 12, 45, 
              0, 1, 0, 2, 3, 4, 0, 0 ,0])
我想打印0之间的所有数字,并自动将它们添加到新的
np.array
(见下文):


是否有内置函数来执行此操作?

您可以使用np获得零的索引。其中:

zeros = np.where(a == 0)[0]
并在每对上迭代以分割数组:

[a[i+1:j] for i, j in zip(zeros, zeros[1:]) if len(a[i+1:j])>0]

Out[46]: 
[array([3, 5]),
 array([10, 14, 15, 56]),
 array([12, 23, 45, 23, 12, 45]),
 array([1]),
 array([2, 3, 4])]
您可以使用
itertools
中的
groupby()
函数,并将
键指定为零或非零的布尔条件。这样,所有连续的零和非零都将分组在一起。使用
if
过滤器拾取非零分组,并使用
list
将非零分组转换为列表

from itertools import groupby
[list(g) for k, g in groupby(a, lambda x: x != 0) if k]

# [[3, 5], [10, 14, 15, 56], [12, 23, 45, 23, 12, 45], [1], [2, 3, 4]]

不需要numpy,此lambda函数在列表上工作,但我们可以在进出时将numpy数组与列表进行转换:

cut = lambda x: [j for j in [cut(x[:x.index(0)])]+cut(x[x.index(0)+1:]) if j] if x.count(0) else x

numpy.array(cut(list(a)))

# array([[3, 5, 5], [10, 14, 15, 56], [12, 23, 45, 23, 12, 45], [1], [2, 3, 4]], dtype=object)
NumPy的
split()
where()
在列表中:

[x[x!=0] for x in np.split(a, np.where(a==0)[0]) if len(x[x!=0])]

[array([3, 5, 5]),
 array([10, 14, 15, 56]),
 array([12, 23, 45, 23, 12, 45]),
 array([1]),
 array([2, 3, 4])]

这是一个使用和的矢量化方法-

样本运行-

In [23]: a
Out[23]: 
array([ 0,  3,  5,  5,  0, 10, 14, 15, 56,  0,  0,  0, 12, 23, 45, 23, 12,
       45,  0,  1,  0,  2,  3,  4,  0,  0,  0])

In [24]: idx = np.where(a!=0)[0]

In [25]: np.split(a[idx],np.where(np.diff(idx)!=1)[0]+1)
Out[25]: 
[array([3, 5, 5]),
 array([10, 14, 15, 56]),
 array([12, 23, 45, 23, 12, 45]),
 array([1]),
 array([2, 3, 4])]

这可能是最糟糕的方法,但也可以将数组转换为字符串,然后将该字符串拆分几次:

long_string = "_".join(a.astype(str))

while long_string.startswith("0_"):
    long_string = long_string.removeprefix("0_")
while long_string.endswith("_0"):
    long_string = long_string.removesuffix("_0")

result = [list(map(int, i.split("_"))) for i in long_string.split("_0_")]

# result: [[3, 5, 5], [10, 14, 15, 56], [12, 23, 45, 23, 12, 45], [1], [2, 3, 4]]

对于
.removeprefix()
.removesuffix()

您需要Python 3.9,如果数组以非零整数开始,例如
a=np.array([1,0,3,5,0,0,10,0])
@Alexander It输出
[3,5]
[10]
,则此解决方案不起作用。这不是正确的吗?对于我上面给出的示例,它应该是[[1]、[3,5]、[10]]@Alexander 1的左边不应该有0,可以认为是在0之间吗?这很公平。您的答案似乎解决了OP所要求的问题(尽管这个问题可以解释为将数组拆分为零)。
In [23]: a
Out[23]: 
array([ 0,  3,  5,  5,  0, 10, 14, 15, 56,  0,  0,  0, 12, 23, 45, 23, 12,
       45,  0,  1,  0,  2,  3,  4,  0,  0,  0])

In [24]: idx = np.where(a!=0)[0]

In [25]: np.split(a[idx],np.where(np.diff(idx)!=1)[0]+1)
Out[25]: 
[array([3, 5, 5]),
 array([10, 14, 15, 56]),
 array([12, 23, 45, 23, 12, 45]),
 array([1]),
 array([2, 3, 4])]
long_string = "_".join(a.astype(str))

while long_string.startswith("0_"):
    long_string = long_string.removeprefix("0_")
while long_string.endswith("_0"):
    long_string = long_string.removesuffix("_0")

result = [list(map(int, i.split("_"))) for i in long_string.split("_0_")]

# result: [[3, 5, 5], [10, 14, 15, 56], [12, 23, 45, 23, 12, 45], [1], [2, 3, 4]]