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 行。
我有一个只用 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 行。