一个由等间距点组成的三维网格

4

我想创建一个列表,其中包含网格上定期间隔点的3-D坐标,每个坐标都是一个3元组。我正在寻求如何以最有效率的方式实现此目的。

例如在 C++ 中,我只需循环三个嵌套循环,一个用于每个坐标。在 Matlab 中,我可能会使用meshgrid函数(可以一次完成)。我已经了解了Python中的meshgrid和mgrid,并且也知道numpy的广播规则更加高效。我认为,在numpy的广播规则和zip函数的结合下使用可能是最有效的方法,但是numpy似乎没有overload zip函数。

5个回答

4

您可以使用 ogrid 替代 meshgrid 和 mgrid,它是 mgrid 的“稀疏”版本。也就是说,仅填充沿值发生变化的维度。其他维度则简单地广播。与非稀疏版本相比,对于大网格,这将节省大量内存。

例如:

>>> import numpy as np
>>> x, y = np.ogrid[-1:2, -2:3]
>>> x
array([[-1],
      [ 0],
      [ 1]])
>>> y
array([[-2, -1,  0,  1,  2]])
>>> x**2 + y**2
array([[5, 2, 1, 2, 5],
      [4, 1, 0, 1, 4],
      [5, 2, 1, 2, 5]])

4
使用ndindex
import numpy as np
ind=np.ndindex(3,3,2)
for i in ind:
    print(i)

# (0, 0, 0)
# (0, 0, 1)
# (0, 1, 0)
# (0, 1, 1)
# (0, 2, 0)
# (0, 2, 1)
# (1, 0, 0)
# (1, 0, 1)
# (1, 1, 0)
# (1, 1, 1)
# (1, 2, 0)
# (1, 2, 1)
# (2, 0, 0)
# (2, 0, 1)
# (2, 1, 0)
# (2, 1, 1)
# (2, 2, 0)
# (2, 2, 1)

2

如果您需要使用非整数坐标,我建议您选择meshgridmgrid。我很惊讶Numpy的广播规则会更有效率,因为meshgrid是专门为解决您要解决的问题而设计的。


1
广播允许在处理大型网格时使用更少的内存。请参阅有关使用 ogrid 的答案。 - rephorm
@rephorm:确实(+1),在过去的两年中我学到了这个。 :) - Eric O. Lebigot

1

对于多维(大于2)的网格,可以使用 numpy.lib.index_tricks.nd_grid,如下所示:

import numpy
grid = numpy.lib.index_tricks.nd_grid()
g1 = grid[:3,:3,:3]
g2 = grid[0:1:0.5, 0:1, 0:2]
g3 = grid[0:1:3j, 0:1:2j, 0:2:2j]

其中g1具有x值为[0,1,2], g2具有x值为[0,.5], g3具有x值为[0.0,0.5,1.0](3j定义步数而不是步增量。有关更多详细信息,请参见文档)。


你也可以直接使用numpy.mgrid,它只是numpy.lib.index_tricks.nd_grid的一个实例。 - rephorm

0

这里有一个高效的选项,类似于您的C++解决方案,我已经用于完全相同的目的:

import numpy, itertools, collections
def grid(xmin, xmax, xstep, ymin, ymax, ystep, zmin, zmax, zstep):
    "return nested tuples of grid-sampled coordinates that include maxima"
    return collections.deque( itertools.product( 
        numpy.arange(xmin, xmax+xstep, xstep).tolist(),
        numpy.arange(ymin, ymax+ystep, ystep).tolist(),
        numpy.arange(zmin, zmax+zstep, zstep).tolist() ) )

在我的测试中,使用a.tolist()的性能最佳,如上所示,但您也可以使用a.flat代替,并删除deque()以获取将节省内存的迭代器。当然,您也可以使用普通的tuple()或list()而不是deque(),但会稍微降低性能(同样,在我的测试中)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接