繁体   English   中英

Python向量化的平行线段的最大值

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM