【问题标题】:Generate a n-dimensional array of coordinates in numpy在numpy中生成一个n维坐标数组
【发布时间】:2016-11-05 07:52:47
【问题描述】:

假设我有一个函数 f,它可以将坐标作为参数并返回一个整数(在本例中为 f(x))。坐标可以是多维的并且是列表的形式。我的目标是用两个坐标之间的所有值填充一个 numpy 数组。我试图列出所有可能的索引并将其用作矢量化函数的输入。

这是我的二维坐标代码:

import itertools
import numpy


def index_array(lower_corner, upper_corner):
     x_range = range(lower_corner[0], upper_corner[0])
     y_range = range(lower_corner[1], upper_corner[1])
     return numpy.array(list(itertools.product(x_range, y_range)))


print(index_array([2, -2], [5, 3]))

这将返回预期的索引列表:

[[ 2 -2]
 [ 2 -1]
 [ 2  0]
 [ 2  1]
 [ 2  2]
 [ 3 -2]
 [ 3 -1]
 [ 3  0]
 [ 3  1]
 [ 3  2]
 [ 4 -2]
 [ 4 -1]
 [ 4  0]
 [ 4  1]
 [ 4  2]]

这是我对 n 维的尝试:

import itertools
import numpy


def f(x):
    # dummy function
    return x + 5


def index_array(lower_corner, upper_corner):
    # returns all indices between two n-dimensional points
    range_list = []
    for n in range(len(lower_corner)):
        range_list.append(range(lower_corner[n], upper_corner[n]))
    return numpy.array(list(itertools.product(*range_list)))


lower_corner = numpy.array([2, -2])
upper_corner = numpy.array([5, 3])
indices = index_array(lower_corner, upper_corner)
vect_func = numpy.vectorize(f)
results = vect_func(indices)
print(results)

虽然这可行,但速度很慢并且需要大量内存。是否有可能以更有效的方式编写它?我可以考虑使用 numpy.meshgrid 但我不知道如何使用它。

【问题讨论】:

    标签: python numpy multidimensional-array iterator coordinates


    【解决方案1】:

    确实,np.meshgrid 是使用一些stacking 的一种方法,如下所示 -

    def ndim_grid(start,stop):
        # Set number of dimensions
        ndims = len(start)
    
        # List of ranges across all dimensions
        L = [np.arange(start[i],stop[i]) for i in range(ndims)]
    
        # Finally use meshgrid to form all combinations corresponding to all 
        # dimensions and stack them as M x ndims array
        return np.hstack((np.meshgrid(*L))).swapaxes(0,1).reshape(ndims,-1).T
    

    示例运行

    1)2D案例:

    In [97]: ndim_grid([2, -2],[5, 3])
    Out[97]: 
    array([[ 2, -2],
           [ 2, -1],
           [ 2,  0],
           [ 2,  1],
           [ 2,  2],
           [ 3, -2],
           [ 3, -1],
           [ 3,  0],
           [ 3,  1],
           [ 3,  2],
           [ 4, -2],
           [ 4, -1],
           [ 4,  0],
           [ 4,  1],
           [ 4,  2]])
    

    2)3D案例:

    In [98]: ndim_grid([2, -2, 4],[5, 3, 6])
    Out[98]: 
    array([[ 2, -2,  4],
           [ 2, -2,  5],
           [ 2, -1,  4],
           [ 2, -1,  5],
           [ 2,  0,  4],
           [ 2,  0,  5],
           [ 2,  1,  4],
           [ 2,  1,  5],
           [ 2,  2,  4],
           [ 2,  2,  5],
           [ 3, -2,  4],
           [ 3, -2,  5],
           [ 3, -1,  4],
           [ 3, -1,  5],
           [ 3,  0,  4],
           [ 3,  0,  5],
           [ 3,  1,  4],
           [ 3,  1,  5],
           [ 3,  2,  4],
           [ 3,  2,  5],
           [ 4, -2,  4],
           [ 4, -2,  5],
           [ 4, -1,  4],
           [ 4, -1,  5],
           [ 4,  0,  4],
           [ 4,  0,  5],
           [ 4,  1,  4],
           [ 4,  1,  5],
           [ 4,  2,  4],
           [ 4,  2,  5]])
    

    【讨论】:

      【解决方案2】:

      另一种选择是使用itertools 中的product,如果角落高于2D,这也适用:

      import itertools as it
      lower_corner = [2, -2]
      upper_corner = [5, 3]
      [coord for coord in it.product(*[range(r[0], r[1]) for r in zip(lower_corner, upper_corner)])]
      
      [(2, -2),
       (2, -1),
       (2, 0),
       (2, 1),
       (2, 2),
       (3, -2),
       (3, -1),
       (3, 0),
       (3, 1),
       (3, 2),
       (4, -2),
       (4, -1),
       (4, 0),
       (4, 1),
       (4, 2)]
      

      【讨论】:

      • 呃,我已经在使用来自 itertoolsproduct 了。它隐藏在第二个函数的返回中:D。但是感谢更紧凑的 for 循环!
      • 您可以将range(r[0], r[1]) 更改为range(*r)。您还使用了一个立即解包的列表理解。您可以改用 gen exp(即 *(range(*r) ... )[] 替换为 ())并避免创建该临时列表。
      • @Bakuriu 完美运行,感谢您指出这一点。我相信这是一个更高效、更简洁的解决方案。
      • ty,这是解决这个问题的一个优雅而简单的解决方案。我会补充一点:如果已经有一个向量列表,只需将该列表替换为 it.product(*my_vector_list) 并放弃均匀间距生成器/列表。这概括了解或非均匀空间向量。
      猜你喜欢
      • 2019-10-21
      • 1970-01-01
      • 2020-03-20
      • 2021-11-24
      • 2011-06-14
      • 2020-09-16
      • 2021-06-04
      • 1970-01-01
      相关资源
      最近更新 更多