Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python矢量化平行线段的最大运行长度_Python_Numpy - Fatal编程技术网

Python矢量化平行线段的最大运行长度

Python矢量化平行线段的最大运行长度,python,numpy,Python,Numpy,我在一个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]]) 我想算

我在一个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]])
我想算出线段上的运行最大值。也就是说,在上面的示例中,对于[0,25]范围内的x,我想要对应的最大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=np.arange(np.min(A[:,0]),np.max(A[:,1]))
最大值=np.0((x.shape[0],2))
最大值[:,0]=x
maxes[:,1]=-np.inf
对于a中的a:
ix=(x>=a[0])&(x

与上面的输出示例相反,此代码输出一个数组,该数组中每x对应一行。两者都很好(并且是等效的)。

您可以使用
布尔型数组对数组进行索引。这意味着您可以根据您的条件一次检查所有坐标,然后对值列进行索引(
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]))

您可以使用布尔数组来确定空间中的给定点是否位于给定的线段中。该布尔数组可以与线段值相乘以生成一个数组,其中线段上的每个点都有一个线段值向量,如果线段不包含该点,则该线段的值为零。从该数组开始的
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]]
将numpy导入为np
A=np.数组([[0,10,4],
[5,19,3],
[6,25,2],
[7,16,1],
[12,21,5]])
#获取空间的维度
seg_left=A[:,0,无]
seg_right=A[:,1,无]
seg_val=A[:,2,无]
#设置空间的左边缘并重置轴
left_edge=seg_left.min()
seg_左-=左_边
seg_右-=左_边
right\u edge=seg\u right.max()
#生成一个坐标数组,并对每个定义的线段重复该数组
#然后可用于确定每个点的线段
空间=np.瓷砖(np.arange(右边缘+1),(分段值大小,1))
空格bool=np.逻辑和(空格>=seg\u左,
空格
Add sample case for the numpy array?另外,段之间是否有重叠?@Divakar:谢谢你的问题。如果你是指示例数组,请参阅我在第一个代码块中提供的示例。是的,可能有重叠;请参阅第一个代码块中的示例。@Matt我想Divakar正在谈论添加一个可执行的示例案例对于数组,它可以复制到python控制台,并将生成一个与您提供的示例数据完全相同的数组。@Scotty1-好的,添加了代码段。希望能澄清它。@Scotty1-完成。感谢您帮助澄清问题。太好了!感谢.Props为任何x坐标范围提供了通用解决方案。唯一的专业我的问题是,因为我有数以万计的段,
空间
数组将占用约47GB的内存,这不合适。但也许我可以以某种方式将其分块,然后应用更正来处理分块转换。分块应该可以工作。你可以研究的另一件事是稀疏矩阵。如果你的段相对较少简而言之,这将释放大量空间。我不太确定如何在没有for循环的情况下构建稀疏矩阵,但这可能会节省大量时间。仅供参考,最后,我完成了以下操作:创建表单的段数组,其中键入{start,end}坐标是起始坐标或结束坐标,具体取决于类型。然后循环通过它,并使用
sortedcontainers.SortedDict
保持最大值。这需要3秒,并且没有内存问题。(您的方法需要约60秒,原始for循环需要约6分钟。)。谢谢你的回答,但问题的一个主要部分实际上是计算出你硬编码的
范围:)@Matt哦,那么我误解了你的问题。进一步思考这个问题有什么意义,或者你对另一个答案满意吗?
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]]