[英]Python vectorized running max of parallel line segments
我在numpy数组中有大量独立的平行水平线段。 每个段都有一个起点和终点(x坐标)和一个值(y坐标)。 这些段不一定具有相同的长度(长度=结束-开始)。
指定段的示例矩阵(每行一个段)如下所示:
Start End Value
0 10 4
5 19 3
6 25 2
7 16 1
12 21 5
在代码中
A = np.array([[0,10,4],
[5,19,3],
[6,25,2],
[7,16,1],
[12,21,5]])
我想弄清楚线段上的运行最大值。 也就是说,在上面的示例中,对于x在[0,25)范围内,我想要相应的max y。 与示例相对应的示例输出为
Start End Max
0 10 4
10 12 3
12 21 5
21 25 2
我可以在for循环中执行此操作,但这很慢,因为我有成千上万的段。 我似乎无法想到一种矢量化方法。 谁能
循环代码示例:
x = np.arange(np.min(A[:,0]), np.max(A[:,1]))
maxes = np.zeros((x.shape[0], 2))
maxes[:,0] = x
maxes[:,1] = -np.inf
for a in A:
ix = (x >= a[0]) & (x < a[1]) & (maxes[:,1] < a[2])
maxes[ix,1] = a[2]
与上面的输出示例相反,此代码输出一个数组,该数组中的每个x都有一行。 两者都很好(并等效)。
您可以使用booleans
数组来为数组建立索引。 这意味着您可以一次根据条件检查所有坐标,然后用结果索引值列( A[2]
)。 从您的示例结果中,我认为不应该包含线段的端点,因此以下代码:
import numpy as np
A = np.array(
[[0,10,4],
[5,19,3],
[6,25,2],
[7,16,1],
[12,21,5]]
)
ranges = np.array([
[0,10], [10,12], [12,21], [21,25]
])
for xmin,xmax in ranges:
print(xmin,xmax, np.max(A[~np.logical_or(A[:,1]<=xmin, A[:,0]>=xmax),2]))
重现您想要的结果:
0 10 4
10 12 3
12 21 5
21 25 2
您可以使用布尔数组确定空间中的给定点是否在给定的线段中。 该布尔数组可以与段值相乘以生成一个数组,其中行上的每个点都有一个段值向量,并且如果段不包括该点,则将该段的值清零。 从那里可以沿单个轴应用数组的max
方法。
import numpy as np
A = np.array([[0,10,4],
[5,19,3],
[6,25,2],
[7,16,1],
[12,21,5]])
# get the dimension of the space
seg_left = A[:, 0, None]
seg_right = A[:, 1, None]
seg_val = A[:, 2, None]
# set the left edge of the space and reset the axes
left_edge = seg_left.min()
seg_left -= left_edge
seg_right -= left_edge
right_edge = seg_right.max()
# generate an array of coordinates and repeat it for each defined segment. This
# can then be used to determine what segments are on for each point
space = np.tile(np.arange(right_edge+1), (seg_val.size, 1))
space_bool = np.logical_and(space >= seg_left,
space < seg_right)
# find the maximum of the on segments
seg_max = (seg_val * space_bool).max(axis=0)
# determine the continuous segments. The +1 ensures that the correct value is
# selected
steps = np.r_[0, np.where(np.diff(seg_max))[0]+1]
seg_val = seg_max[steps[:-1]]
# reset the left edge to the original left edge
steps += left_edge
print(np.c_[steps[:-1], steps[1:], seg_val])
# [[ 0 10 4]
# [10 12 3]
# [12 21 5]
# [21 25 2]]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.