以numpy生成一个n维坐标数组

时间:2022-02-09 21:39:30

Let's say I have a function f which can take coordinates as parameter and returns an integer (f(x) in this case). The coordinates can be multidimensional and are in the form of a list. My goal is to fill a numpy array with all values between two coordinates. I've tried to make a list of all possible indices and use it as input for the vectorized function.

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

Here is my code for 2 dimensional coordinates:

这是我的二维坐标的代码:

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]))

This will return the index list like expected:

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

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

And here is my attempt for n dimensions:

这是我对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)

While this works it's quite slow and needs huge amounts of memory. Is it possible to write this in a more efficient way? I could think about using numpy.meshgrid but I don't know how I would use it.

虽然这是可行的,但它非常慢,需要大量的内存。有没有可能用更有效的方式来写?我可以考虑用numpy。网格,但我不知道该怎么用。

2 个解决方案

#1


5  

Indeed np.meshgrid would be one way to do it with some stacking, as shown below -

事实上np。网格将是一种方法来做一些堆叠,如下所示

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

Sample run

样本运行

1) 2D Case :

1)2 d的例子:

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 Case :

2)3 d的例子:

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


3  

Another option is to use the product from itertools, this also works if the corners are higher than 2D:

另一种选择是使用来自itertools的产品,如果角大于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)]

#1


5  

Indeed np.meshgrid would be one way to do it with some stacking, as shown below -

事实上np。网格将是一种方法来做一些堆叠,如下所示

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

Sample run

样本运行

1) 2D Case :

1)2 d的例子:

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 Case :

2)3 d的例子:

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


3  

Another option is to use the product from itertools, this also works if the corners are higher than 2D:

另一种选择是使用来自itertools的产品,如果角大于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)]