Python 基于值拆分Numpy数组
假设我有一个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+
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]]