Python麻木。如果元素位于一对指定元素之间,则删除二维数组中的一个或多个元素

Python Numpy. Delete an element (or elements) in a 2D array if said element is located between a pair of specified elements

我有一个只用 1 和 0 填充的 2D NumPy 数组。

a = [[0 0 0 0 1 0 0 0 1]
     [1 1 1 1 1 1 1 1 1]
     [1 1 1 1 1 1 1 1 1]
     [1 1 1 1 0 0 0 0 1]
     [1 1 1 1 1 1 1 1 1]
     [1 1 1 0 1 1 1 1 1]
     [1 1 1 1 1 1 0 0 1]
     [1 1 1 1 1 1 1 1 1]]

为了获取 0 的位置,我使用了以下代码:

new_array = np.transpose(np.nonzero(a==0))

正如预期的那样,我得到以下结果显示数组中 0 的位置

new_array = [[0 0]
             [0 1]
             [0 2]
             [0 3]
             [0 5]
             [0 6]
             [0 7]
             [3 4]
             [3 5]
             [3 6]
             [3 7]
             [5 3]
             [6 6]
             [6 7]]

现在我的问题是: 如果所述组大于 2,是否有办法在水平组的开始和结束处获取 0 的位置?

编辑:如果一组在一行的末尾完成并继续在它下面的一组,它将被视为 2 个独立的组。

我的第一个想法是实现一个删除位于 0 之间的 0 的过程,但我不知道该怎么做。

我希望“new_array”输出为:

new_array = [[0 0]
             [0 3]
             [0 5]
             [0 7]
             [3 4]
             [3 7]
             [5 3]
             [6 6]
             [6 7]]

谢谢!!

编辑 2:

感谢大家提供的非常有用的见解,我能够解决我遇到的问题。

为了满足好奇心,这个数据代表了音乐信息。我正在开发的程序的目的是根据图像(仅由水平线组成)创建乐谱。

完成图像到 1 和 0 的转换后,我需要从中提取以下信息:起始、音高和持续时间。这转化为“x”轴上的位置、“y”轴上的位置和组的总长度。

由于 X 和 Y 位置很容易获得,我决定将它们与“持续时间”计算分开处理(这是 post 中要解决的主要问题)。

感谢您的帮助,我解决了 Duration 问题并创建了一个包含所有必要信息的新数组:

[[0 0 4]
 [5 0 3]
 [4 3 4]
 [6 6 2]]

请注意,第 1 列代表开始,第 2 列代表音高,第 3 列代表持续时间。

我还注意到建议为每个事件添加标识符的评论。最终我需要实现它来区分不同的乐器(然后将它们发送到各个 Midi 通道)。但是,对于仅旨在为单个乐器创建乐谱的程序的第一次迭代,没有必要,因为所有事件都属于单个乐器。

我的编程经验很少,我不知道这是否是实现我目标的最有效方式。欢迎任何建议。

谢谢!

一个更容易遵循的可能解决方案是:

b = np.diff(a, prepend=1)  # prepend a column of 1s and detect
                           # jumps between adjacent columns (left to right)
y, x = np.where(b > 0)  # find positions of the jumps 0->1 (left to right)
# shift positive jumps to the left by 1 position while filling gaps with 0:
b[y, x - 1] = 1
b[y, x] = 0
new_array = list(zip(*np.where(b)))

另一个是:

new_array = list(zip(*np.where(np.diff(a, n=2, prepend=1, append=1) > 0)))

两种解决方案均基于计算连续列之间差异的 np.diff(当 axis=-1 用于二维数组时)。

另一个解决方案的一个缺陷是它报告 所有 个序列 的零,不管它们的长度。 您的预期输出也包含这样的组,由 1 或 2 零,但我认为不应该。

我的解决方案没有上述缺陷。

处理相邻个相等元素组的优雅工具是 itertools.groupby,所以从:

开始
import itertools

然后将您的预期结果生成为:

res = []
for rowIdx, row in enumerate(a):
    colIdx = 0  # Start column index
    for k, grp in itertools.groupby(row):
        vals = list(grp)        # Values in the group
        lgth = len(vals)        # Length of the group
        colIdx2 = colIdx + lgth - 1  # End column index
        if k == 0 and lgth > 2: # Record this group
            res.append([rowIdx, colIdx])
            res.append([rowIdx, colIdx2])
        colIdx = colIdx2 + 1    # Advance column index
result = np.array(res)

您的源数据的结果是:

array([[0, 0],
       [0, 3],
       [0, 5],
       [0, 7],
       [3, 4],
       [3, 7]])

如您所见,它不包括更短的零序列 在第 5 行和第 6 行。